Merge changes from topic 'upgrade-mockito-2.7.13'

* changes:
  Reimplement compatibility classes against 2.7.13
  Modify the build and add necessary libraries
  Upgrade to Mockito v2.7.13
diff --git a/Android.mk b/Android.mk
index ce5294b..b7be989 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,16 +23,17 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src/main/java) \
-    $(call all-java-files-under, cglib-and-asm/src)
+    $(call all-java-files-under, src/main/java)
 
-LOCAL_JAVA_LIBRARIES := junit-host objenesis-host ant
+LOCAL_JAVA_LIBRARIES := junit-host objenesis-host
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    mockito-byte-buddy-host \
+    mockito-byte-buddy-agent-host
 LOCAL_MODULE := mockito-host
 LOCAL_MODULE_TAGS := optional
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 include $(BUILD_HOST_JAVA_LIBRARY)
 
-
 ###################################################################
 # Target build
 ###################################################################
@@ -44,26 +45,10 @@
 
 # Exclude source used to dynamically create classes since target builds use 
 # dexmaker instead and including it causes conflicts.
-explicit_target_excludes := \
-    src/main/java/org/mockito/internal/creation/AbstractMockitoMethodProxy.java \
-    src/main/java/org/mockito/internal/creation/AcrossJVMSerializationFeature.java \
-    src/main/java/org/mockito/internal/creation/CglibMockMaker.java \
-    src/main/java/org/mockito/internal/creation/DelegatingMockitoMethodProxy.java \
-    src/main/java/org/mockito/internal/creation/MethodInterceptorFilter.java \
-    src/main/java/org/mockito/internal/creation/MockitoMethodProxy.java \
-    src/main/java/org/mockito/internal/creation/SerializableMockitoMethodProxy.java \
-    src/main/java/org/mockito/internal/invocation/realmethod/FilteredCGLIBProxyRealMethod.java \
-    src/main/java/org/mockito/internal/invocation/realmethod/CGLIBProxyRealMethod.java \
-    src/main/java/org/mockito/internal/invocation/realmethod/HasCGLIBMethodProxy.java
-
 target_src_files := \
     $(call all-java-files-under, src/main/java)
 target_src_files := \
-    $(filter-out src/main/java/org/mockito/internal/creation/cglib/%, $(target_src_files))
-target_src_files := \
-    $(filter-out src/main/java/org/mockito/internal/creation/jmock/%, $(target_src_files))
-target_src_files := \
-    $(filter-out $(explicit_target_excludes), $(target_src_files))
+    $(filter-out src/main/java/org/mockito/internal/creation/bytebuddy/%, $(target_src_files))
 
 LOCAL_SRC_FILES := $(target_src_files)
 LOCAL_JAVA_LIBRARIES := junit objenesis-target
@@ -112,6 +97,15 @@
 include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
 endif # HOST_OS == linux
 
+# Host prebuilt dependencies.
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_JAVA_LIBRARIES := \
+    mockito-byte-buddy-host:lib/byte-buddy-1.6.9$(COMMON_JAVA_PACKAGE_SUFFIX) \
+    mockito-byte-buddy-agent-host:lib/byte-buddy-agent-1.6.9$(COMMON_JAVA_PACKAGE_SUFFIX) \
+
+include $(BUILD_HOST_PREBUILT)
 
 ###################################################
 # Clean up temp vars
diff --git a/README.android b/README.android
deleted file mode 100644
index db40633..0000000
--- a/README.android
+++ /dev/null
@@ -1,14 +0,0 @@
-URL: https://github.com/mockito/mockito
-Version: v1.10.19
-License: Apache 2.0
-Description: Mockito is a mocking framework with a clean and simple API.
-
-For Android, we need to combine Mockito with a MockMaker provided by the
-Dexmaker module.
-
-The source can be updated using the update_source.sh script.
-
-Local Modifications:
-      Fixed some generic/casting issues probably caused by stricter compiler.
-      Fixed compiler failure caused by upstream mismatch between the cglib-and-asm
-            source and prebuilt library.
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..a010c10
--- /dev/null
+++ b/README.version
@@ -0,0 +1,12 @@
+URL: https://github.com/mockito/mockito
+Version: v2.7.13
+License: Apache 2.0
+Description: Mockito is a mocking framework with a clean and simple API.
+
+For Android, we need to combine Mockito with a MockMaker provided by the
+Dexmaker module.
+
+The source can be updated using the update_source.sh script.
+
+Local Modifications:
+        Add compatibility classes to aid in upgrade from 1.10.19
diff --git a/cglib-and-asm/.gitignore b/cglib-and-asm/.gitignore
deleted file mode 100644
index f2e671b..0000000
--- a/cglib-and-asm/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build-eclipse/
diff --git a/cglib-and-asm/README.TXT b/cglib-and-asm/README.TXT
deleted file mode 100644
index 82180d7..0000000
--- a/cglib-and-asm/README.TXT
+++ /dev/null
@@ -1,5 +0,0 @@
-This mockito subproject repackages cglib + asm to avoid problems with conflicting versions.

-

-Unfortunately, jarjar was not able to repackage sources 

-therefore I'm using this subproject to repackage cglib+asm.

-We should NEVER modify cglib/asm - sources are here only for the sake of repackaging.
\ No newline at end of file
diff --git a/cglib-and-asm/licenses/asm-license.txt b/cglib-and-asm/licenses/asm-license.txt
deleted file mode 100644
index fe0bf7d..0000000
--- a/cglib-and-asm/licenses/asm-license.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Copyright (c) 2000-2005 INRIA, France Telecom

-All rights reserved.

-

-Redistribution and use in source and binary forms, with or without

-modification, are permitted provided that the following conditions

-are met:

-

-1. Redistributions of source code must retain the above copyright

-   notice, this list of conditions and the following disclaimer.

-

-2. Redistributions in binary form must reproduce the above copyright

-   notice, this list of conditions and the following disclaimer in the

-   documentation and/or other materials provided with the distribution.

-

-3. Neither the name of the copyright holders nor the names of its

-   contributors may be used to endorse or promote products derived from

-   this software without specific prior written permission.

-

-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

-THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/cglib-and-asm/licenses/cglib-license.txt b/cglib-and-asm/licenses/cglib-license.txt
deleted file mode 100644
index f49a4e1..0000000
--- a/cglib-and-asm/licenses/cglib-license.txt
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   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.
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/AnnotationVisitor.java b/cglib-and-asm/src/org/mockito/asm/AnnotationVisitor.java
deleted file mode 100644
index 3a96c7d..0000000
--- a/cglib-and-asm/src/org/mockito/asm/AnnotationVisitor.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A visitor to visit a Java annotation. The methods of this interface must be

- * called in the following order: (<tt>visit<tt> | <tt>visitEnum<tt> | 

- * <tt>visitAnnotation<tt> | <tt>visitArray<tt>)* <tt>visitEnd<tt>.

- *

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public interface AnnotationVisitor {

-

-    /**

-     * Visits a primitive value of the annotation.

-     * 

-     * @param name the value name.

-     * @param value the actual value, whose type must be {@link Byte},

-     *        {@link Boolean}, {@link Character}, {@link Short},

-     *        {@link Integer}, {@link Long}, {@link Float}, {@link Double},

-     *        {@link String} or {@link Type}. This value can also be an array

-     *        of byte, boolean, short, char, int, long, float or double values

-     *        (this is equivalent to using {@link #visitArray visitArray} and

-     *        visiting each array element in turn, but is more convenient).

-     */

-    void visit(String name, Object value);

-

-    /**

-     * Visits an enumeration value of the annotation.

-     * 

-     * @param name the value name.

-     * @param desc the class descriptor of the enumeration class.

-     * @param value the actual enumeration value.

-     */

-    void visitEnum(String name, String desc, String value);

-

-    /**

-     * Visits a nested annotation value of the annotation.

-     * 

-     * @param name the value name.

-     * @param desc the class descriptor of the nested annotation class.

-     * @return a visitor to visit the actual nested annotation value, or

-     *         <tt>null</tt> if this visitor is not interested in visiting

-     *         this nested annotation. <i>The nested annotation value must be

-     *         fully visited before calling other methods on this annotation

-     *         visitor</i>.

-     */

-    AnnotationVisitor visitAnnotation(String name, String desc);

-

-    /**

-     * Visits an array value of the annotation. Note that arrays of primitive

-     * types (such as byte, boolean, short, char, int, long, float or double)

-     * can be passed as value to {@link #visit visit}. This is what

-     * {@link ClassReader} does.

-     * 

-     * @param name the value name.

-     * @return a visitor to visit the actual array value elements, or

-     *         <tt>null</tt> if this visitor is not interested in visiting

-     *         these values. The 'name' parameters passed to the methods of this

-     *         visitor are ignored. <i>All the array values must be visited

-     *         before calling other methods on this annotation visitor</i>.

-     */

-    AnnotationVisitor visitArray(String name);

-

-    /**

-     * Visits the end of the annotation.

-     */

-    void visitEnd();

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/AnnotationWriter.java b/cglib-and-asm/src/org/mockito/asm/AnnotationWriter.java
deleted file mode 100644
index 1723f55..0000000
--- a/cglib-and-asm/src/org/mockito/asm/AnnotationWriter.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * An {@link AnnotationVisitor} that generates annotations in bytecode form.

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-final class AnnotationWriter implements AnnotationVisitor {

-

-    /**

-     * The class writer to which this annotation must be added.

-     */

-    private final ClassWriter cw;

-

-    /**

-     * The number of values in this annotation.

-     */

-    private int size;

-

-    /**

-     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation 

-     * writers used for annotation default and annotation arrays use unnamed

-     * values.

-     */

-    private final boolean named;

-

-    /**

-     * The annotation values in bytecode form. This byte vector only contains

-     * the values themselves, i.e. the number of values must be stored as a

-     * unsigned short just before these bytes.

-     */

-    private final ByteVector bv;

-

-    /**

-     * The byte vector to be used to store the number of values of this

-     * annotation. See {@link #bv}.

-     */

-    private final ByteVector parent;

-

-    /**

-     * Where the number of values of this annotation must be stored in

-     * {@link #parent}.

-     */

-    private final int offset;

-

-    /**

-     * Next annotation writer. This field is used to store annotation lists.

-     */

-    AnnotationWriter next;

-

-    /**

-     * Previous annotation writer. This field is used to store annotation lists.

-     */

-    AnnotationWriter prev;

-

-    // ------------------------------------------------------------------------

-    // Constructor

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a new {@link AnnotationWriter}.

-     * 

-     * @param cw the class writer to which this annotation must be added.

-     * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.

-     * @param bv where the annotation values must be stored.

-     * @param parent where the number of annotation values must be stored.

-     * @param offset where in <tt>parent</tt> the number of annotation values must 

-     *      be stored.

-     */

-    AnnotationWriter(

-        final ClassWriter cw,

-        final boolean named,

-        final ByteVector bv,

-        final ByteVector parent,

-        final int offset)

-    {

-        this.cw = cw;

-        this.named = named;

-        this.bv = bv;

-        this.parent = parent;

-        this.offset = offset;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the AnnotationVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(final String name, final Object value) {

-        ++size;

-        if (named) {

-            bv.putShort(cw.newUTF8(name));

-        }

-        if (value instanceof String) {

-            bv.put12('s', cw.newUTF8((String) value));

-        } else if (value instanceof Byte) {

-            bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);

-        } else if (value instanceof Boolean) {

-            int v = ((Boolean) value).booleanValue() ? 1 : 0;

-            bv.put12('Z', cw.newInteger(v).index);

-        } else if (value instanceof Character) {

-            bv.put12('C', cw.newInteger(((Character) value).charValue()).index);

-        } else if (value instanceof Short) {

-            bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);

-        } else if (value instanceof Type) {

-            bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));

-        } else if (value instanceof byte[]) {

-            byte[] v = (byte[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('B', cw.newInteger(v[i]).index);

-            }

-        } else if (value instanceof boolean[]) {

-            boolean[] v = (boolean[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);

-            }

-        } else if (value instanceof short[]) {

-            short[] v = (short[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('S', cw.newInteger(v[i]).index);

-            }

-        } else if (value instanceof char[]) {

-            char[] v = (char[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('C', cw.newInteger(v[i]).index);

-            }

-        } else if (value instanceof int[]) {

-            int[] v = (int[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('I', cw.newInteger(v[i]).index);

-            }

-        } else if (value instanceof long[]) {

-            long[] v = (long[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('J', cw.newLong(v[i]).index);

-            }

-        } else if (value instanceof float[]) {

-            float[] v = (float[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('F', cw.newFloat(v[i]).index);

-            }

-        } else if (value instanceof double[]) {

-            double[] v = (double[]) value;

-            bv.put12('[', v.length);

-            for (int i = 0; i < v.length; i++) {

-                bv.put12('D', cw.newDouble(v[i]).index);

-            }

-        } else {

-            Item i = cw.newConstItem(value);

-            bv.put12(".s.IFJDCS".charAt(i.type), i.index);

-        }

-    }

-

-    public void visitEnum(

-        final String name,

-        final String desc,

-        final String value)

-    {

-        ++size;

-        if (named) {

-            bv.putShort(cw.newUTF8(name));

-        }

-        bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String name,

-        final String desc)

-    {

-        ++size;

-        if (named) {

-            bv.putShort(cw.newUTF8(name));

-        }

-        // write tag and type, and reserve space for values count

-        bv.put12('@', cw.newUTF8(desc)).putShort(0);

-        return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);

-    }

-

-    public AnnotationVisitor visitArray(final String name) {

-        ++size;

-        if (named) {

-            bv.putShort(cw.newUTF8(name));

-        }

-        // write tag, and reserve space for array size

-        bv.put12('[', 0);

-        return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);

-    }

-

-    public void visitEnd() {

-        if (parent != null) {

-            byte[] data = parent.data;

-            data[offset] = (byte) (size >>> 8);

-            data[offset + 1] = (byte) size;

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the size of this annotation writer list.

-     * 

-     * @return the size of this annotation writer list.

-     */

-    int getSize() {

-        int size = 0;

-        AnnotationWriter aw = this;

-        while (aw != null) {

-            size += aw.bv.length;

-            aw = aw.next;

-        }

-        return size;

-    }

-

-    /**

-     * Puts the annotations of this annotation writer list into the given byte

-     * vector.

-     * 

-     * @param out where the annotations must be put.

-     */

-    void put(final ByteVector out) {

-        int n = 0;

-        int size = 2;

-        AnnotationWriter aw = this;

-        AnnotationWriter last = null;

-        while (aw != null) {

-            ++n;

-            size += aw.bv.length;

-            aw.visitEnd(); // in case user forgot to call visitEnd

-            aw.prev = last;

-            last = aw;

-            aw = aw.next;

-        }

-        out.putInt(size);

-        out.putShort(n);

-        aw = last;

-        while (aw != null) {

-            out.putByteArray(aw.bv.data, 0, aw.bv.length);

-            aw = aw.prev;

-        }

-    }

-

-    /**

-     * Puts the given annotation lists into the given byte vector.

-     * 

-     * @param panns an array of annotation writer lists.

-     * @param off index of the first annotation to be written.

-     * @param out where the annotations must be put.

-     */

-    static void put(

-        final AnnotationWriter[] panns,

-        final int off,

-        final ByteVector out)

-    {

-        int size = 1 + 2 * (panns.length - off);

-        for (int i = off; i < panns.length; ++i) {

-            size += panns[i] == null ? 0 : panns[i].getSize();

-        }

-        out.putInt(size).putByte(panns.length - off);

-        for (int i = off; i < panns.length; ++i) {

-            AnnotationWriter aw = panns[i];

-            AnnotationWriter last = null;

-            int n = 0;

-            while (aw != null) {

-                ++n;

-                aw.visitEnd(); // in case user forgot to call visitEnd

-                aw.prev = last;

-                last = aw;

-                aw = aw.next;

-            }

-            out.putShort(n);

-            aw = last;

-            while (aw != null) {

-                out.putByteArray(aw.bv.data, 0, aw.bv.length);

-                aw = aw.prev;

-            }

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Attribute.java b/cglib-and-asm/src/org/mockito/asm/Attribute.java
deleted file mode 100644
index 3cea49a..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Attribute.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A non standard class, field, method or code attribute.

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public class Attribute {

-

-    /**

-     * The type of this attribute.

-     */

-    public final String type;

-

-    /**

-     * The raw value of this attribute, used only for unknown attributes.

-     */

-    byte[] value;

-

-    /**

-     * The next attribute in this attribute list. May be <tt>null</tt>.

-     */

-    Attribute next;

-

-    /**

-     * Constructs a new empty attribute.

-     * 

-     * @param type the type of the attribute.

-     */

-    protected Attribute(final String type) {

-        this.type = type;

-    }

-

-    /**

-     * Returns <tt>true</tt> if this type of attribute is unknown. The default

-     * implementation of this method always returns <tt>true</tt>.

-     * 

-     * @return <tt>true</tt> if this type of attribute is unknown.

-     */

-    public boolean isUnknown() {

-        return true;

-    }

-

-    /**

-     * Returns <tt>true</tt> if this type of attribute is a code attribute.

-     * 

-     * @return <tt>true</tt> if this type of attribute is a code attribute.

-     */

-    public boolean isCodeAttribute() {

-        return false;

-    }

-

-    /**

-     * Returns the labels corresponding to this attribute.

-     * 

-     * @return the labels corresponding to this attribute, or <tt>null</tt> if

-     *         this attribute is not a code attribute that contains labels.

-     */

-    protected Label[] getLabels() {

-        return null;

-    }

-

-    /**

-     * Reads a {@link #type type} attribute. This method must return a <i>new</i>

-     * {@link Attribute} object, of type {@link #type type}, corresponding to

-     * the <tt>len</tt> bytes starting at the given offset, in the given class

-     * reader.

-     * 

-     * @param cr the class that contains the attribute to be read.

-     * @param off index of the first byte of the attribute's content in {@link

-     *        ClassReader#b cr.b}. The 6 attribute header bytes, containing the

-     *        type and the length of the attribute, are not taken into account

-     *        here.

-     * @param len the length of the attribute's content.

-     * @param buf buffer to be used to call

-     *        {@link ClassReader#readUTF8 readUTF8},

-     *        {@link ClassReader#readClass(int,char[]) readClass} or

-     *        {@link ClassReader#readConst readConst}.

-     * @param codeOff index of the first byte of code's attribute content in

-     *        {@link ClassReader#b cr.b}, or -1 if the attribute to be read is

-     *        not a code attribute. The 6 attribute header bytes, containing the

-     *        type and the length of the attribute, are not taken into account

-     *        here.

-     * @param labels the labels of the method's code, or <tt>null</tt> if the

-     *        attribute to be read is not a code attribute.

-     * @return a <i>new</i> {@link Attribute} object corresponding to the given

-     *         bytes.

-     */

-    protected Attribute read(

-        final ClassReader cr,

-        final int off,

-        final int len,

-        final char[] buf,

-        final int codeOff,

-        final Label[] labels)

-    {

-        Attribute attr = new Attribute(type);

-        attr.value = new byte[len];

-        System.arraycopy(cr.b, off, attr.value, 0, len);

-        return attr;

-    }

-

-    /**

-     * Returns the byte array form of this attribute.

-     * 

-     * @param cw the class to which this attribute must be added. This parameter

-     *        can be used to add to the constant pool of this class the items

-     *        that corresponds to this attribute.

-     * @param code the bytecode of the method corresponding to this code

-     *        attribute, or <tt>null</tt> if this attribute is not a code

-     *        attributes.

-     * @param len the length of the bytecode of the method corresponding to this

-     *        code attribute, or <tt>null</tt> if this attribute is not a code

-     *        attribute.

-     * @param maxStack the maximum stack size of the method corresponding to

-     *        this code attribute, or -1 if this attribute is not a code

-     *        attribute.

-     * @param maxLocals the maximum number of local variables of the method

-     *        corresponding to this code attribute, or -1 if this attribute is

-     *        not a code attribute.

-     * @return the byte array form of this attribute.

-     */

-    protected ByteVector write(

-        final ClassWriter cw,

-        final byte[] code,

-        final int len,

-        final int maxStack,

-        final int maxLocals)

-    {

-        ByteVector v = new ByteVector();

-        v.data = value;

-        v.length = value.length;

-        return v;

-    }

-

-    /**

-     * Returns the length of the attribute list that begins with this attribute.

-     * 

-     * @return the length of the attribute list that begins with this attribute.

-     */

-    final int getCount() {

-        int count = 0;

-        Attribute attr = this;

-        while (attr != null) {

-            count += 1;

-            attr = attr.next;

-        }

-        return count;

-    }

-

-    /**

-     * Returns the size of all the attributes in this attribute list.

-     * 

-     * @param cw the class writer to be used to convert the attributes into byte

-     *        arrays, with the {@link #write write} method.

-     * @param code the bytecode of the method corresponding to these code

-     *        attributes, or <tt>null</tt> if these attributes are not code

-     *        attributes.

-     * @param len the length of the bytecode of the method corresponding to

-     *        these code attributes, or <tt>null</tt> if these attributes are

-     *        not code attributes.

-     * @param maxStack the maximum stack size of the method corresponding to

-     *        these code attributes, or -1 if these attributes are not code

-     *        attributes.

-     * @param maxLocals the maximum number of local variables of the method

-     *        corresponding to these code attributes, or -1 if these attributes

-     *        are not code attributes.

-     * @return the size of all the attributes in this attribute list. This size

-     *         includes the size of the attribute headers.

-     */

-    final int getSize(

-        final ClassWriter cw,

-        final byte[] code,

-        final int len,

-        final int maxStack,

-        final int maxLocals)

-    {

-        Attribute attr = this;

-        int size = 0;

-        while (attr != null) {

-            cw.newUTF8(attr.type);

-            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;

-            attr = attr.next;

-        }

-        return size;

-    }

-

-    /**

-     * Writes all the attributes of this attribute list in the given byte

-     * vector.

-     * 

-     * @param cw the class writer to be used to convert the attributes into byte

-     *        arrays, with the {@link #write write} method.

-     * @param code the bytecode of the method corresponding to these code

-     *        attributes, or <tt>null</tt> if these attributes are not code

-     *        attributes.

-     * @param len the length of the bytecode of the method corresponding to

-     *        these code attributes, or <tt>null</tt> if these attributes are

-     *        not code attributes.

-     * @param maxStack the maximum stack size of the method corresponding to

-     *        these code attributes, or -1 if these attributes are not code

-     *        attributes.

-     * @param maxLocals the maximum number of local variables of the method

-     *        corresponding to these code attributes, or -1 if these attributes

-     *        are not code attributes.

-     * @param out where the attributes must be written.

-     */

-    final void put(

-        final ClassWriter cw,

-        final byte[] code,

-        final int len,

-        final int maxStack,

-        final int maxLocals,

-        final ByteVector out)

-    {

-        Attribute attr = this;

-        while (attr != null) {

-            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);

-            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);

-            out.putByteArray(b.data, 0, b.length);

-            attr = attr.next;

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/ByteVector.java b/cglib-and-asm/src/org/mockito/asm/ByteVector.java
deleted file mode 100644
index 3d8ada5..0000000
--- a/cglib-and-asm/src/org/mockito/asm/ByteVector.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A dynamically extensible vector of bytes. This class is roughly equivalent to

- * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.

- * 

- * @author Eric Bruneton

- */

-public class ByteVector {

-

-    /**

-     * The content of this vector.

-     */

-    byte[] data;

-

-    /**

-     * Actual number of bytes in this vector.

-     */

-    int length;

-

-    /**

-     * Constructs a new {@link ByteVector ByteVector} with a default initial

-     * size.

-     */

-    public ByteVector() {

-        data = new byte[64];

-    }

-

-    /**

-     * Constructs a new {@link ByteVector ByteVector} with the given initial

-     * size.

-     * 

-     * @param initialSize the initial size of the byte vector to be constructed.

-     */

-    public ByteVector(final int initialSize) {

-        data = new byte[initialSize];

-    }

-

-    /**

-     * Puts a byte into this byte vector. The byte vector is automatically

-     * enlarged if necessary.

-     * 

-     * @param b a byte.

-     * @return this byte vector.

-     */

-    public ByteVector putByte(final int b) {

-        int length = this.length;

-        if (length + 1 > data.length) {

-            enlarge(1);

-        }

-        data[length++] = (byte) b;

-        this.length = length;

-        return this;

-    }

-

-    /**

-     * Puts two bytes into this byte vector. The byte vector is automatically

-     * enlarged if necessary.

-     * 

-     * @param b1 a byte.

-     * @param b2 another byte.

-     * @return this byte vector.

-     */

-    ByteVector put11(final int b1, final int b2) {

-        int length = this.length;

-        if (length + 2 > data.length) {

-            enlarge(2);

-        }

-        byte[] data = this.data;

-        data[length++] = (byte) b1;

-        data[length++] = (byte) b2;

-        this.length = length;

-        return this;

-    }

-

-    /**

-     * Puts a short into this byte vector. The byte vector is automatically

-     * enlarged if necessary.

-     * 

-     * @param s a short.

-     * @return this byte vector.

-     */

-    public ByteVector putShort(final int s) {

-        int length = this.length;

-        if (length + 2 > data.length) {

-            enlarge(2);

-        }

-        byte[] data = this.data;

-        data[length++] = (byte) (s >>> 8);

-        data[length++] = (byte) s;

-        this.length = length;

-        return this;

-    }

-

-    /**

-     * Puts a byte and a short into this byte vector. The byte vector is

-     * automatically enlarged if necessary.

-     * 

-     * @param b a byte.

-     * @param s a short.

-     * @return this byte vector.

-     */

-    ByteVector put12(final int b, final int s) {

-        int length = this.length;

-        if (length + 3 > data.length) {

-            enlarge(3);

-        }

-        byte[] data = this.data;

-        data[length++] = (byte) b;

-        data[length++] = (byte) (s >>> 8);

-        data[length++] = (byte) s;

-        this.length = length;

-        return this;

-    }

-

-    /**

-     * Puts an int into this byte vector. The byte vector is automatically

-     * enlarged if necessary.

-     * 

-     * @param i an int.

-     * @return this byte vector.

-     */

-    public ByteVector putInt(final int i) {

-        int length = this.length;

-        if (length + 4 > data.length) {

-            enlarge(4);

-        }

-        byte[] data = this.data;

-        data[length++] = (byte) (i >>> 24);

-        data[length++] = (byte) (i >>> 16);

-        data[length++] = (byte) (i >>> 8);

-        data[length++] = (byte) i;

-        this.length = length;

-        return this;

-    }

-

-    /**

-     * Puts a long into this byte vector. The byte vector is automatically

-     * enlarged if necessary.

-     * 

-     * @param l a long.

-     * @return this byte vector.

-     */

-    public ByteVector putLong(final long l) {

-        int length = this.length;

-        if (length + 8 > data.length) {

-            enlarge(8);

-        }

-        byte[] data = this.data;

-        int i = (int) (l >>> 32);

-        data[length++] = (byte) (i >>> 24);

-        data[length++] = (byte) (i >>> 16);

-        data[length++] = (byte) (i >>> 8);

-        data[length++] = (byte) i;

-        i = (int) l;

-        data[length++] = (byte) (i >>> 24);

-        data[length++] = (byte) (i >>> 16);

-        data[length++] = (byte) (i >>> 8);

-        data[length++] = (byte) i;

-        this.length = length;

-        return this;

-    }

-

-    /**

-     * Puts an UTF8 string into this byte vector. The byte vector is

-     * automatically enlarged if necessary.

-     * 

-     * @param s a String.

-     * @return this byte vector.

-     */

-    public ByteVector putUTF8(final String s) {

-        int charLength = s.length();

-        if (length + 2 + charLength > data.length) {

-            enlarge(2 + charLength);

-        }

-        int len = length;

-        byte[] data = this.data;

-        // optimistic algorithm: instead of computing the byte length and then

-        // serializing the string (which requires two loops), we assume the byte

-        // length is equal to char length (which is the most frequent case), and

-        // we start serializing the string right away. During the serialization,

-        // if we find that this assumption is wrong, we continue with the

-        // general method.

-        data[len++] = (byte) (charLength >>> 8);

-        data[len++] = (byte) charLength;

-        for (int i = 0; i < charLength; ++i) {

-            char c = s.charAt(i);

-            if (c >= '\001' && c <= '\177') {

-                data[len++] = (byte) c;

-            } else {

-                int byteLength = i;

-                for (int j = i; j < charLength; ++j) {

-                    c = s.charAt(j);

-                    if (c >= '\001' && c <= '\177') {

-                        byteLength++;

-                    } else if (c > '\u07FF') {

-                        byteLength += 3;

-                    } else {

-                        byteLength += 2;

-                    }

-                }

-                data[length] = (byte) (byteLength >>> 8);

-                data[length + 1] = (byte) byteLength;

-                if (length + 2 + byteLength > data.length) {

-                    length = len;

-                    enlarge(2 + byteLength);

-                    data = this.data;

-                }

-                for (int j = i; j < charLength; ++j) {

-                    c = s.charAt(j);

-                    if (c >= '\001' && c <= '\177') {

-                        data[len++] = (byte) c;

-                    } else if (c > '\u07FF') {

-                        data[len++] = (byte) (0xE0 | c >> 12 & 0xF);

-                        data[len++] = (byte) (0x80 | c >> 6 & 0x3F);

-                        data[len++] = (byte) (0x80 | c & 0x3F);

-                    } else {

-                        data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);

-                        data[len++] = (byte) (0x80 | c & 0x3F);

-                    }

-                }

-                break;

-            }

-        }

-        length = len;

-        return this;

-    }

-

-    /**

-     * Puts an array of bytes into this byte vector. The byte vector is

-     * automatically enlarged if necessary.

-     * 

-     * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>

-     *        null bytes into this byte vector.

-     * @param off index of the fist byte of b that must be copied.

-     * @param len number of bytes of b that must be copied.

-     * @return this byte vector.

-     */

-    public ByteVector putByteArray(final byte[] b, final int off, final int len)

-    {

-        if (length + len > data.length) {

-            enlarge(len);

-        }

-        if (b != null) {

-            System.arraycopy(b, off, data, length, len);

-        }

-        length += len;

-        return this;

-    }

-

-    /**

-     * Enlarge this byte vector so that it can receive n more bytes.

-     * 

-     * @param size number of additional bytes that this byte vector should be

-     *        able to receive.

-     */

-    private void enlarge(final int size) {

-        int length1 = 2 * data.length;

-        int length2 = length + size;

-        byte[] newData = new byte[length1 > length2 ? length1 : length2];

-        System.arraycopy(data, 0, newData, 0, length);

-        data = newData;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/ClassAdapter.java b/cglib-and-asm/src/org/mockito/asm/ClassAdapter.java
deleted file mode 100644
index 8e88dbc..0000000
--- a/cglib-and-asm/src/org/mockito/asm/ClassAdapter.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * An empty {@link ClassVisitor} that delegates to another {@link ClassVisitor}.

- * This class can be used as a super class to quickly implement usefull class

- * adapter classes, just by overriding the necessary methods.

- * 

- * @author Eric Bruneton

- */

-public class ClassAdapter implements ClassVisitor {

-

-    /**

-     * The {@link ClassVisitor} to which this adapter delegates calls.

-     */

-    protected ClassVisitor cv;

-

-    /**

-     * Constructs a new {@link ClassAdapter} object.

-     * 

-     * @param cv the class visitor to which this adapter must delegate calls.

-     */

-    public ClassAdapter(final ClassVisitor cv) {

-        this.cv = cv;

-    }

-

-    public void visit(

-        final int version,

-        final int access,

-        final String name,

-        final String signature,

-        final String superName,

-        final String[] interfaces)

-    {

-        cv.visit(version, access, name, signature, superName, interfaces);

-    }

-

-    public void visitSource(final String source, final String debug) {

-        cv.visitSource(source, debug);

-    }

-

-    public void visitOuterClass(

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        cv.visitOuterClass(owner, name, desc);

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        return cv.visitAnnotation(desc, visible);

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        cv.visitAttribute(attr);

-    }

-

-    public void visitInnerClass(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        cv.visitInnerClass(name, outerName, innerName, access);

-    }

-

-    public FieldVisitor visitField(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        return cv.visitField(access, name, desc, signature, value);

-    }

-

-    public MethodVisitor visitMethod(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        return cv.visitMethod(access, name, desc, signature, exceptions);

-    }

-

-    public void visitEnd() {

-        cv.visitEnd();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/ClassReader.java b/cglib-and-asm/src/org/mockito/asm/ClassReader.java
deleted file mode 100644
index decb377..0000000
--- a/cglib-and-asm/src/org/mockito/asm/ClassReader.java
+++ /dev/null
@@ -1,2009 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-import java.io.InputStream;

-import java.io.IOException;

-

-/**

- * A Java class parser to make a {@link ClassVisitor} visit an existing class.

- * This class parses a byte array conforming to the Java class file format and

- * calls the appropriate visit methods of a given class visitor for each field,

- * method and bytecode instruction encountered.

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public class ClassReader {

-

-    /**

-     * True to enable signatures support.

-     */

-    static final boolean SIGNATURES = true;

-    

-    /**

-     * True to enable annotations support.

-     */

-    static final boolean ANNOTATIONS = true;

-    

-    /**

-     * True to enable stack map frames support.

-     */

-    static final boolean FRAMES = true;

-    

-    /**

-     * True to enable bytecode writing support.

-     */

-    static final boolean WRITER = true;

-    

-    /**

-     * True to enable JSR_W and GOTO_W support.

-     */

-    static final boolean RESIZE = true;

-    

-    /**

-     * Flag to skip method code. If this class is set <code>CODE</code>

-     * attribute won't be visited. This can be used, for example, to retrieve

-     * annotations for methods and method parameters.

-     */

-    public static final int SKIP_CODE = 1;

-

-    /**

-     * Flag to skip the debug information in the class. If this flag is set the

-     * debug information of the class is not visited, i.e. the

-     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and

-     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be

-     * called.

-     */

-    public static final int SKIP_DEBUG = 2;

-

-    /**

-     * Flag to skip the stack map frames in the class. If this flag is set the

-     * stack map frames of the class is not visited, i.e. the

-     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.

-     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is

-     * used: it avoids visiting frames that will be ignored and recomputed from

-     * scratch in the class writer.

-     */

-    public static final int SKIP_FRAMES = 4;

-

-    /**

-     * Flag to expand the stack map frames. By default stack map frames are

-     * visited in their original format (i.e. "expanded" for classes whose

-     * version is less than V1_6, and "compressed" for the other classes). If

-     * this flag is set, stack map frames are always visited in expanded format

-     * (this option adds a decompression/recompression step in ClassReader and

-     * ClassWriter which degrades performances quite a lot).

-     */

-    public static final int EXPAND_FRAMES = 8;

-

-    /**

-     * The class to be parsed. <i>The content of this array must not be

-     * modified. This field is intended for {@link Attribute} sub classes, and

-     * is normally not needed by class generators or adapters.</i>

-     */

-    public final byte[] b;

-

-    /**

-     * The start index of each constant pool item in {@link #b b}, plus one.

-     * The one byte offset skips the constant pool item tag that indicates its

-     * type.

-     */

-    private final int[] items;

-

-    /**

-     * The String objects corresponding to the CONSTANT_Utf8 items. This cache

-     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,

-     * which GREATLY improves performances (by a factor 2 to 3). This caching

-     * strategy could be extended to all constant pool items, but its benefit

-     * would not be so great for these items (because they are much less

-     * expensive to parse than CONSTANT_Utf8 items).

-     */

-    private final String[] strings;

-

-    /**

-     * Maximum length of the strings contained in the constant pool of the

-     * class.

-     */

-    private final int maxStringLength;

-

-    /**

-     * Start index of the class header information (access, name...) in

-     * {@link #b b}.

-     */

-    public final int header;

-

-    // ------------------------------------------------------------------------

-    // Constructors

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a new {@link ClassReader} object.

-     * 

-     * @param b the bytecode of the class to be read.

-     */

-    public ClassReader(final byte[] b) {

-        this(b, 0, b.length);

-    }

-

-    /**

-     * Constructs a new {@link ClassReader} object.

-     * 

-     * @param b the bytecode of the class to be read.

-     * @param off the start offset of the class data.

-     * @param len the length of the class data.

-     */

-    public ClassReader(final byte[] b, final int off, final int len) {

-        this.b = b;

-        // parses the constant pool

-        items = new int[readUnsignedShort(off + 8)];

-        int n = items.length;

-        strings = new String[n];

-        int max = 0;

-        int index = off + 10;

-        for (int i = 1; i < n; ++i) {

-            items[i] = index + 1;

-            int size;

-            switch (b[index]) {

-                case ClassWriter.FIELD:

-                case ClassWriter.METH:

-                case ClassWriter.IMETH:

-                case ClassWriter.INT:

-                case ClassWriter.FLOAT:

-                case ClassWriter.NAME_TYPE:

-                    size = 5;

-                    break;

-                case ClassWriter.LONG:

-                case ClassWriter.DOUBLE:

-                    size = 9;

-                    ++i;

-                    break;

-                case ClassWriter.UTF8:

-                    size = 3 + readUnsignedShort(index + 1);

-                    if (size > max) {

-                        max = size;

-                    }

-                    break;

-                // case ClassWriter.CLASS:

-                // case ClassWriter.STR:

-                default:

-                    size = 3;

-                    break;

-            }

-            index += size;

-        }

-        maxStringLength = max;

-        // the class header information starts just after the constant pool

-        header = index;

-    }

-

-    /**

-     * Returns the class's access flags (see {@link Opcodes}). This value may

-     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5

-     * and those flags are represented by attributes.

-     * 

-     * @return the class access flags

-     * 

-     * @see ClassVisitor#visit(int, int, String, String, String, String[])

-     */

-    public int getAccess() {

-        return readUnsignedShort(header);

-    }

-

-    /**

-     * Returns the internal name of the class (see

-     * {@link Type#getInternalName() getInternalName}).

-     * 

-     * @return the internal class name

-     * 

-     * @see ClassVisitor#visit(int, int, String, String, String, String[])

-     */

-    public String getClassName() {

-        return readClass(header + 2, new char[maxStringLength]);

-    }

-

-    /**

-     * Returns the internal of name of the super class (see

-     * {@link Type#getInternalName() getInternalName}). For interfaces, the

-     * super class is {@link Object}.

-     * 

-     * @return the internal name of super class, or <tt>null</tt> for

-     *         {@link Object} class.

-     * 

-     * @see ClassVisitor#visit(int, int, String, String, String, String[])

-     */

-    public String getSuperName() {

-        int n = items[readUnsignedShort(header + 4)];

-        return n == 0 ? null : readUTF8(n, new char[maxStringLength]);

-    }

-

-    /**

-     * Returns the internal names of the class's interfaces (see

-     * {@link Type#getInternalName() getInternalName}).

-     * 

-     * @return the array of internal names for all implemented interfaces or

-     *         <tt>null</tt>.

-     * 

-     * @see ClassVisitor#visit(int, int, String, String, String, String[])

-     */

-    public String[] getInterfaces() {

-        int index = header + 6;

-        int n = readUnsignedShort(index);

-        String[] interfaces = new String[n];

-        if (n > 0) {

-            char[] buf = new char[maxStringLength];

-            for (int i = 0; i < n; ++i) {

-                index += 2;

-                interfaces[i] = readClass(index, buf);

-            }

-        }

-        return interfaces;

-    }

-

-    /**

-     * Copies the constant pool data into the given {@link ClassWriter}. Should

-     * be called before the {@link #accept(ClassVisitor,int)} method.

-     * 

-     * @param classWriter the {@link ClassWriter} to copy constant pool into.

-     */

-    void copyPool(final ClassWriter classWriter) {

-        char[] buf = new char[maxStringLength];

-        int ll = items.length;

-        Item[] items2 = new Item[ll];

-        for (int i = 1; i < ll; i++) {

-            int index = items[i];

-            int tag = b[index - 1];

-            Item item = new Item(i);

-            int nameType;

-            switch (tag) {

-                case ClassWriter.FIELD:

-                case ClassWriter.METH:

-                case ClassWriter.IMETH:

-                    nameType = items[readUnsignedShort(index + 2)];

-                    item.set(tag,

-                            readClass(index, buf),

-                            readUTF8(nameType, buf),

-                            readUTF8(nameType + 2, buf));

-                    break;

-

-                case ClassWriter.INT:

-                    item.set(readInt(index));

-                    break;

-

-                case ClassWriter.FLOAT:

-                    item.set(Float.intBitsToFloat(readInt(index)));

-                    break;

-

-                case ClassWriter.NAME_TYPE:

-                    item.set(tag,

-                            readUTF8(index, buf),

-                            readUTF8(index + 2, buf),

-                            null);

-                    break;

-

-                case ClassWriter.LONG:

-                    item.set(readLong(index));

-                    ++i;

-                    break;

-

-                case ClassWriter.DOUBLE:

-                    item.set(Double.longBitsToDouble(readLong(index)));

-                    ++i;

-                    break;

-

-                case ClassWriter.UTF8: {

-                    String s = strings[i];

-                    if (s == null) {

-                        index = items[i];

-                        s = strings[i] = readUTF(index + 2,

-                                readUnsignedShort(index),

-                                buf);

-                    }

-                    item.set(tag, s, null, null);

-                }

-                    break;

-

-                // case ClassWriter.STR:

-                // case ClassWriter.CLASS:

-                default:

-                    item.set(tag, readUTF8(index, buf), null, null);

-                    break;

-            }

-

-            int index2 = item.hashCode % items2.length;

-            item.next = items2[index2];

-            items2[index2] = item;

-        }

-

-        int off = items[1] - 1;

-        classWriter.pool.putByteArray(b, off, header - off);

-        classWriter.items = items2;

-        classWriter.threshold = (int) (0.75d * ll);

-        classWriter.index = ll;

-    }

-

-    /**

-     * Constructs a new {@link ClassReader} object.

-     * 

-     * @param is an input stream from which to read the class.

-     * @throws IOException if a problem occurs during reading.

-     */

-    public ClassReader(final InputStream is) throws IOException {

-        this(readClass(is));

-    }

-

-    /**

-     * Constructs a new {@link ClassReader} object.

-     * 

-     * @param name the fully qualified name of the class to be read.

-     * @throws IOException if an exception occurs during reading.

-     */

-    public ClassReader(final String name) throws IOException {

-        this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')

-                + ".class"));

-    }

-

-    /**

-     * Reads the bytecode of a class.

-     * 

-     * @param is an input stream from which to read the class.

-     * @return the bytecode read from the given input stream.

-     * @throws IOException if a problem occurs during reading.

-     */

-    private static byte[] readClass(final InputStream is) throws IOException {

-        if (is == null) {

-            throw new IOException("Class not found");

-        }

-        byte[] b = new byte[is.available()];

-        int len = 0;

-        while (true) {

-            int n = is.read(b, len, b.length - len);

-            if (n == -1) {

-                if (len < b.length) {

-                    byte[] c = new byte[len];

-                    System.arraycopy(b, 0, c, 0, len);

-                    b = c;

-                }

-                return b;

-            }

-            len += n;

-            if (len == b.length) {

-                byte[] c = new byte[b.length + 1000];

-                System.arraycopy(b, 0, c, 0, len);

-                b = c;

-            }

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Public methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Makes the given visitor visit the Java class of this {@link ClassReader}.

-     * This class is the one specified in the constructor (see

-     * {@link #ClassReader(byte[]) ClassReader}).

-     * 

-     * @param classVisitor the visitor that must visit this class.

-     * @param flags option flags that can be used to modify the default behavior

-     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},

-     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.

-     */

-    public void accept(final ClassVisitor classVisitor, final int flags) {

-        accept(classVisitor, new Attribute[0], flags);

-    }

-

-    /**

-     * Makes the given visitor visit the Java class of this {@link ClassReader}.

-     * This class is the one specified in the constructor (see

-     * {@link #ClassReader(byte[]) ClassReader}).

-     * 

-     * @param classVisitor the visitor that must visit this class.

-     * @param attrs prototypes of the attributes that must be parsed during the

-     *        visit of the class. Any attribute whose type is not equal to the

-     *        type of one the prototypes will not be parsed: its byte array

-     *        value will be passed unchanged to the ClassWriter. <i>This may

-     *        corrupt it if this value contains references to the constant pool,

-     *        or has syntactic or semantic links with a class element that has

-     *        been transformed by a class adapter between the reader and the

-     *        writer</i>.

-     * @param flags option flags that can be used to modify the default behavior

-     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},

-     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.

-     */

-    public void accept(

-        final ClassVisitor classVisitor,

-        final Attribute[] attrs,

-        final int flags)

-    {

-        byte[] b = this.b; // the bytecode array

-        char[] c = new char[maxStringLength]; // buffer used to read strings

-        int i, j, k; // loop variables

-        int u, v, w; // indexes in b

-        Attribute attr;

-

-        int access;

-        String name;

-        String desc;

-        String attrName;

-        String signature;

-        int anns = 0;

-        int ianns = 0;

-        Attribute cattrs = null;

-

-        // visits the header

-        u = header;

-        access = readUnsignedShort(u);

-        name = readClass(u + 2, c);

-        v = items[readUnsignedShort(u + 4)];

-        String superClassName = v == 0 ? null : readUTF8(v, c);

-        String[] implementedItfs = new String[readUnsignedShort(u + 6)];

-        w = 0;

-        u += 8;

-        for (i = 0; i < implementedItfs.length; ++i) {

-            implementedItfs[i] = readClass(u, c);

-            u += 2;

-        }

-

-        boolean skipCode = (flags & SKIP_CODE) != 0;

-        boolean skipDebug = (flags & SKIP_DEBUG) != 0;

-        boolean unzip = (flags & EXPAND_FRAMES) != 0;

-

-        // skips fields and methods

-        v = u;

-        i = readUnsignedShort(v);

-        v += 2;

-        for (; i > 0; --i) {

-            j = readUnsignedShort(v + 6);

-            v += 8;

-            for (; j > 0; --j) {

-                v += 6 + readInt(v + 2);

-            }

-        }

-        i = readUnsignedShort(v);

-        v += 2;

-        for (; i > 0; --i) {

-            j = readUnsignedShort(v + 6);

-            v += 8;

-            for (; j > 0; --j) {

-                v += 6 + readInt(v + 2);

-            }

-        }

-        // reads the class's attributes

-        signature = null;

-        String sourceFile = null;

-        String sourceDebug = null;

-        String enclosingOwner = null;

-        String enclosingName = null;

-        String enclosingDesc = null;

-

-        i = readUnsignedShort(v);

-        v += 2;

-        for (; i > 0; --i) {

-            attrName = readUTF8(v, c);

-            // tests are sorted in decreasing frequency order

-            // (based on frequencies observed on typical classes)

-            if ("SourceFile".equals(attrName)) {

-                sourceFile = readUTF8(v + 6, c);

-            } else if ("InnerClasses".equals(attrName)) {

-                w = v + 6;

-            } else if ("EnclosingMethod".equals(attrName)) {

-                enclosingOwner = readClass(v + 6, c);

-                int item = readUnsignedShort(v + 8);

-                if (item != 0) {

-                    enclosingName = readUTF8(items[item], c);

-                    enclosingDesc = readUTF8(items[item] + 2, c);

-                }

-            } else if (SIGNATURES && "Signature".equals(attrName)) {

-                signature = readUTF8(v + 6, c);

-            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {

-                anns = v + 6;

-            } else if ("Deprecated".equals(attrName)) {

-                access |= Opcodes.ACC_DEPRECATED;

-            } else if ("Synthetic".equals(attrName)) {

-                access |= Opcodes.ACC_SYNTHETIC;

-            } else if ("SourceDebugExtension".equals(attrName)) {

-                int len = readInt(v + 2);

-                sourceDebug = readUTF(v + 6, len, new char[len]);

-            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {

-                ianns = v + 6;

-            } else {

-                attr = readAttribute(attrs,

-                        attrName,

-                        v + 6,

-                        readInt(v + 2),

-                        c,

-                        -1,

-                        null);

-                if (attr != null) {

-                    attr.next = cattrs;

-                    cattrs = attr;

-                }

-            }

-            v += 6 + readInt(v + 2);

-        }

-        // calls the visit method

-        classVisitor.visit(readInt(4),

-                access,

-                name,

-                signature,

-                superClassName,

-                implementedItfs);

-

-        // calls the visitSource method

-        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {

-            classVisitor.visitSource(sourceFile, sourceDebug);

-        }

-

-        // calls the visitOuterClass method

-        if (enclosingOwner != null) {

-            classVisitor.visitOuterClass(enclosingOwner,

-                    enclosingName,

-                    enclosingDesc);

-        }

-

-        // visits the class annotations

-        if (ANNOTATIONS) {

-            for (i = 1; i >= 0; --i) {

-                v = i == 0 ? ianns : anns;

-                if (v != 0) {

-                    j = readUnsignedShort(v);

-                    v += 2;

-                    for (; j > 0; --j) {

-                        v = readAnnotationValues(v + 2,

-                                c,

-                                true,

-                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));

-                    }

-                }

-            }

-        }

-

-        // visits the class attributes

-        while (cattrs != null) {

-            attr = cattrs.next;

-            cattrs.next = null;

-            classVisitor.visitAttribute(cattrs);

-            cattrs = attr;

-        }

-

-        // calls the visitInnerClass method

-        if (w != 0) {

-            i = readUnsignedShort(w);

-            w += 2;

-            for (; i > 0; --i) {

-                classVisitor.visitInnerClass(readUnsignedShort(w) == 0

-                        ? null

-                        : readClass(w, c), readUnsignedShort(w + 2) == 0

-                        ? null

-                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0

-                        ? null

-                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));

-                w += 8;

-            }

-        }

-

-        // visits the fields

-        i = readUnsignedShort(u);

-        u += 2;

-        for (; i > 0; --i) {

-            access = readUnsignedShort(u);

-            name = readUTF8(u + 2, c);

-            desc = readUTF8(u + 4, c);

-            // visits the field's attributes and looks for a ConstantValue

-            // attribute

-            int fieldValueItem = 0;

-            signature = null;

-            anns = 0;

-            ianns = 0;

-            cattrs = null;

-

-            j = readUnsignedShort(u + 6);

-            u += 8;

-            for (; j > 0; --j) {

-                attrName = readUTF8(u, c);

-                // tests are sorted in decreasing frequency order

-                // (based on frequencies observed on typical classes)

-                if ("ConstantValue".equals(attrName)) {

-                    fieldValueItem = readUnsignedShort(u + 6);

-                } else if (SIGNATURES && "Signature".equals(attrName)) {

-                    signature = readUTF8(u + 6, c);

-                } else if ("Deprecated".equals(attrName)) {

-                    access |= Opcodes.ACC_DEPRECATED;

-                } else if ("Synthetic".equals(attrName)) {

-                    access |= Opcodes.ACC_SYNTHETIC;

-                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {

-                    anns = u + 6;

-                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {

-                    ianns = u + 6;

-                } else {

-                    attr = readAttribute(attrs,

-                            attrName,

-                            u + 6,

-                            readInt(u + 2),

-                            c,

-                            -1,

-                            null);

-                    if (attr != null) {

-                        attr.next = cattrs;

-                        cattrs = attr;

-                    }

-                }

-                u += 6 + readInt(u + 2);

-            }

-            // visits the field

-            FieldVisitor fv = classVisitor.visitField(access,

-                    name,

-                    desc,

-                    signature,

-                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));

-            // visits the field annotations and attributes

-            if (fv != null) {

-                if (ANNOTATIONS) {

-                    for (j = 1; j >= 0; --j) {

-                        v = j == 0 ? ianns : anns;

-                        if (v != 0) {

-                            k = readUnsignedShort(v);

-                            v += 2;

-                            for (; k > 0; --k) {

-                                v = readAnnotationValues(v + 2,

-                                        c,

-                                        true,

-                                        fv.visitAnnotation(readUTF8(v, c), j != 0));

-                            }

-                        }

-                    }

-                }

-                while (cattrs != null) {

-                    attr = cattrs.next;

-                    cattrs.next = null;

-                    fv.visitAttribute(cattrs);

-                    cattrs = attr;

-                }

-                fv.visitEnd();

-            }

-        }

-

-        // visits the methods

-        i = readUnsignedShort(u);

-        u += 2;

-        for (; i > 0; --i) {

-            int u0 = u + 6;

-            access = readUnsignedShort(u);

-            name = readUTF8(u + 2, c);

-            desc = readUTF8(u + 4, c);

-            signature = null;

-            anns = 0;

-            ianns = 0;

-            int dann = 0;

-            int mpanns = 0;

-            int impanns = 0;

-            cattrs = null;

-            v = 0;

-            w = 0;

-

-            // looks for Code and Exceptions attributes

-            j = readUnsignedShort(u + 6);

-            u += 8;

-            for (; j > 0; --j) {

-                attrName = readUTF8(u, c);

-                int attrSize = readInt(u + 2);

-                u += 6;

-                // tests are sorted in decreasing frequency order

-                // (based on frequencies observed on typical classes)

-                if ("Code".equals(attrName)) {

-                    if (!skipCode) {

-                        v = u;

-                    }

-                } else if ("Exceptions".equals(attrName)) {

-                    w = u;

-                } else if (SIGNATURES && "Signature".equals(attrName)) {

-                    signature = readUTF8(u, c);

-                } else if ("Deprecated".equals(attrName)) {

-                    access |= Opcodes.ACC_DEPRECATED;

-                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {

-                    anns = u;

-                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {

-                    dann = u;

-                } else if ("Synthetic".equals(attrName)) {

-                    access |= Opcodes.ACC_SYNTHETIC;

-                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {

-                    ianns = u;

-                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))

-                {

-                    mpanns = u;

-                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))

-                {

-                    impanns = u;

-                } else {

-                    attr = readAttribute(attrs,

-                            attrName,

-                            u,

-                            attrSize,

-                            c,

-                            -1,

-                            null);

-                    if (attr != null) {

-                        attr.next = cattrs;

-                        cattrs = attr;

-                    }

-                }

-                u += attrSize;

-            }

-            // reads declared exceptions

-            String[] exceptions;

-            if (w == 0) {

-                exceptions = null;

-            } else {

-                exceptions = new String[readUnsignedShort(w)];

-                w += 2;

-                for (j = 0; j < exceptions.length; ++j) {

-                    exceptions[j] = readClass(w, c);

-                    w += 2;

-                }

-            }

-

-            // visits the method's code, if any

-            MethodVisitor mv = classVisitor.visitMethod(access,

-                    name,

-                    desc,

-                    signature,

-                    exceptions);

-

-            if (mv != null) {

-                /*

-                 * if the returned MethodVisitor is in fact a MethodWriter, it

-                 * means there is no method adapter between the reader and the

-                 * writer. If, in addition, the writer's constant pool was

-                 * copied from this reader (mw.cw.cr == this), and the signature

-                 * and exceptions of the method have not been changed, then it

-                 * is possible to skip all visit events and just copy the

-                 * original code of the method to the writer (the access, name

-                 * and descriptor can have been changed, this is not important

-                 * since they are not copied as is from the reader).

-                 */

-                if (WRITER && mv instanceof MethodWriter) {

-                    MethodWriter mw = (MethodWriter) mv;

-                    if (mw.cw.cr == this) {

-                        if (signature == mw.signature) {

-                            boolean sameExceptions = false;

-                            if (exceptions == null) {

-                                sameExceptions = mw.exceptionCount == 0;

-                            } else {

-                                if (exceptions.length == mw.exceptionCount) {

-                                    sameExceptions = true;

-                                    for (j = exceptions.length - 1; j >= 0; --j)

-                                    {

-                                        w -= 2;

-                                        if (mw.exceptions[j] != readUnsignedShort(w))

-                                        {

-                                            sameExceptions = false;

-                                            break;

-                                        }

-                                    }

-                                }

-                            }

-                            if (sameExceptions) {

-                                /*

-                                 * we do not copy directly the code into

-                                 * MethodWriter to save a byte array copy

-                                 * operation. The real copy will be done in

-                                 * ClassWriter.toByteArray().

-                                 */

-                                mw.classReaderOffset = u0;

-                                mw.classReaderLength = u - u0;

-                                continue;

-                            }

-                        }

-                    }

-                }

-

-                if (ANNOTATIONS && dann != 0) {

-                    AnnotationVisitor dv = mv.visitAnnotationDefault();

-                    readAnnotationValue(dann, c, null, dv);

-                    if (dv != null) {

-                        dv.visitEnd();

-                    }

-                }

-                if (ANNOTATIONS) {

-                    for (j = 1; j >= 0; --j) {

-                        w = j == 0 ? ianns : anns;

-                        if (w != 0) {

-                            k = readUnsignedShort(w);

-                            w += 2;

-                            for (; k > 0; --k) {

-                                w = readAnnotationValues(w + 2,

-                                        c,

-                                        true,

-                                        mv.visitAnnotation(readUTF8(w, c), j != 0));

-                            }

-                        }

-                    }

-                }

-                if (ANNOTATIONS && mpanns != 0) {

-                    readParameterAnnotations(mpanns, desc, c, true, mv);

-                }

-                if (ANNOTATIONS && impanns != 0) {

-                    readParameterAnnotations(impanns, desc, c, false, mv);

-                }

-                while (cattrs != null) {

-                    attr = cattrs.next;

-                    cattrs.next = null;

-                    mv.visitAttribute(cattrs);

-                    cattrs = attr;

-                }

-            }

-

-            if (mv != null && v != 0) {

-                int maxStack = readUnsignedShort(v);

-                int maxLocals = readUnsignedShort(v + 2);

-                int codeLength = readInt(v + 4);

-                v += 8;

-

-                int codeStart = v;

-                int codeEnd = v + codeLength;

-

-                mv.visitCode();

-

-                // 1st phase: finds the labels

-                int label;

-                Label[] labels = new Label[codeLength + 2];

-                readLabel(codeLength + 1, labels);

-                while (v < codeEnd) {

-                    w = v - codeStart;

-                    int opcode = b[v] & 0xFF;

-                    switch (ClassWriter.TYPE[opcode]) {

-                        case ClassWriter.NOARG_INSN:

-                        case ClassWriter.IMPLVAR_INSN:

-                            v += 1;

-                            break;

-                        case ClassWriter.LABEL_INSN:

-                            readLabel(w + readShort(v + 1), labels);

-                            v += 3;

-                            break;

-                        case ClassWriter.LABELW_INSN:

-                            readLabel(w + readInt(v + 1), labels);

-                            v += 5;

-                            break;

-                        case ClassWriter.WIDE_INSN:

-                            opcode = b[v + 1] & 0xFF;

-                            if (opcode == Opcodes.IINC) {

-                                v += 6;

-                            } else {

-                                v += 4;

-                            }

-                            break;

-                        case ClassWriter.TABL_INSN:

-                            // skips 0 to 3 padding bytes*

-                            v = v + 4 - (w & 3);

-                            // reads instruction

-                            readLabel(w + readInt(v), labels);

-                            j = readInt(v + 8) - readInt(v + 4) + 1;

-                            v += 12;

-                            for (; j > 0; --j) {

-                                readLabel(w + readInt(v), labels);

-                                v += 4;

-                            }

-                            break;

-                        case ClassWriter.LOOK_INSN:

-                            // skips 0 to 3 padding bytes*

-                            v = v + 4 - (w & 3);

-                            // reads instruction

-                            readLabel(w + readInt(v), labels);

-                            j = readInt(v + 4);

-                            v += 8;

-                            for (; j > 0; --j) {

-                                readLabel(w + readInt(v + 4), labels);

-                                v += 8;

-                            }

-                            break;

-                        case ClassWriter.VAR_INSN:

-                        case ClassWriter.SBYTE_INSN:

-                        case ClassWriter.LDC_INSN:

-                            v += 2;

-                            break;

-                        case ClassWriter.SHORT_INSN:

-                        case ClassWriter.LDCW_INSN:

-                        case ClassWriter.FIELDORMETH_INSN:

-                        case ClassWriter.TYPE_INSN:

-                        case ClassWriter.IINC_INSN:

-                            v += 3;

-                            break;

-                        case ClassWriter.ITFMETH_INSN:

-                            v += 5;

-                            break;

-                        // case MANA_INSN:

-                        default:

-                            v += 4;

-                            break;

-                    }

-                }

-                // parses the try catch entries

-                j = readUnsignedShort(v);

-                v += 2;

-                for (; j > 0; --j) {

-                    Label start = readLabel(readUnsignedShort(v), labels);

-                    Label end = readLabel(readUnsignedShort(v + 2), labels);

-                    Label handler = readLabel(readUnsignedShort(v + 4), labels);

-                    int type = readUnsignedShort(v + 6);

-                    if (type == 0) {

-                        mv.visitTryCatchBlock(start, end, handler, null);

-                    } else {

-                        mv.visitTryCatchBlock(start,

-                                end,

-                                handler,

-                                readUTF8(items[type], c));

-                    }

-                    v += 8;

-                }

-                // parses the local variable, line number tables, and code

-                // attributes

-                int varTable = 0;

-                int varTypeTable = 0;

-                int stackMap = 0;

-                int frameCount = 0;

-                int frameMode = 0;

-                int frameOffset = 0;

-                int frameLocalCount = 0;

-                int frameLocalDiff = 0;

-                int frameStackCount = 0;

-                Object[] frameLocal = null;

-                Object[] frameStack = null;

-                boolean zip = true;

-                cattrs = null;

-                j = readUnsignedShort(v);

-                v += 2;

-                for (; j > 0; --j) {

-                    attrName = readUTF8(v, c);

-                    if ("LocalVariableTable".equals(attrName)) {

-                        if (!skipDebug) {

-                            varTable = v + 6;

-                            k = readUnsignedShort(v + 6);

-                            w = v + 8;

-                            for (; k > 0; --k) {

-                                label = readUnsignedShort(w);

-                                if (labels[label] == null) {

-                                    readLabel(label, labels).status |= Label.DEBUG;

-                                }

-                                label += readUnsignedShort(w + 2);

-                                if (labels[label] == null) {

-                                    readLabel(label, labels).status |= Label.DEBUG;

-                                }

-                                w += 10;

-                            }

-                        }

-                    } else if ("LocalVariableTypeTable".equals(attrName)) {

-                        varTypeTable = v + 6;

-                    } else if ("LineNumberTable".equals(attrName)) {

-                        if (!skipDebug) {

-                            k = readUnsignedShort(v + 6);

-                            w = v + 8;

-                            for (; k > 0; --k) {

-                                label = readUnsignedShort(w);

-                                if (labels[label] == null) {

-                                    readLabel(label, labels).status |= Label.DEBUG;

-                                }

-                                labels[label].line = readUnsignedShort(w + 2);

-                                w += 4;

-                            }

-                        }

-                    } else if (FRAMES && "StackMapTable".equals(attrName)) {

-                        if ((flags & SKIP_FRAMES) == 0) {

-                            stackMap = v + 8;

-                            frameCount = readUnsignedShort(v + 6);

-                        }

-                        /*

-                         * here we do not extract the labels corresponding to

-                         * the attribute content. This would require a full

-                         * parsing of the attribute, which would need to be

-                         * repeated in the second phase (see below). Instead the

-                         * content of the attribute is read one frame at a time

-                         * (i.e. after a frame has been visited, the next frame

-                         * is read), and the labels it contains are also

-                         * extracted one frame at a time. Thanks to the ordering

-                         * of frames, having only a "one frame lookahead" is not

-                         * a problem, i.e. it is not possible to see an offset

-                         * smaller than the offset of the current insn and for

-                         * which no Label exist.

-                         */

-                        // TODO true for frame offsets,

-                        // but for UNINITIALIZED type offsets?

-                    } else if (FRAMES && "StackMap".equals(attrName)) {

-                        if ((flags & SKIP_FRAMES) == 0) {

-                            stackMap = v + 8;

-                            frameCount = readUnsignedShort(v + 6);

-                            zip = false;

-                        }

-                        /*

-                         * IMPORTANT! here we assume that the frames are

-                         * ordered, as in the StackMapTable attribute, although

-                         * this is not guaranteed by the attribute format.

-                         */

-                    } else {

-                        for (k = 0; k < attrs.length; ++k) {

-                            if (attrs[k].type.equals(attrName)) {

-                                attr = attrs[k].read(this,

-                                        v + 6,

-                                        readInt(v + 2),

-                                        c,

-                                        codeStart - 8,

-                                        labels);

-                                if (attr != null) {

-                                    attr.next = cattrs;

-                                    cattrs = attr;

-                                }

-                            }

-                        }

-                    }

-                    v += 6 + readInt(v + 2);

-                }

-

-                // 2nd phase: visits each instruction

-                if (FRAMES && stackMap != 0) {

-                    // creates the very first (implicit) frame from the method

-                    // descriptor

-                    frameLocal = new Object[maxLocals];

-                    frameStack = new Object[maxStack];

-                    if (unzip) {

-                        int local = 0;

-                        if ((access & Opcodes.ACC_STATIC) == 0) {

-                            if ("<init>".equals(name)) {

-                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;

-                            } else {

-                                frameLocal[local++] = readClass(header + 2, c);

-                            }

-                        }

-                        j = 1;

-                        loop: while (true) {

-                            k = j;

-                            switch (desc.charAt(j++)) {

-                                case 'Z':

-                                case 'C':

-                                case 'B':

-                                case 'S':

-                                case 'I':

-                                    frameLocal[local++] = Opcodes.INTEGER;

-                                    break;

-                                case 'F':

-                                    frameLocal[local++] = Opcodes.FLOAT;

-                                    break;

-                                case 'J':

-                                    frameLocal[local++] = Opcodes.LONG;

-                                    break;

-                                case 'D':

-                                    frameLocal[local++] = Opcodes.DOUBLE;

-                                    break;

-                                case '[':

-                                    while (desc.charAt(j) == '[') {

-                                        ++j;

-                                    }

-                                    if (desc.charAt(j) == 'L') {

-                                        ++j;

-                                        while (desc.charAt(j) != ';') {

-                                            ++j;

-                                        }

-                                    }

-                                    frameLocal[local++] = desc.substring(k, ++j);

-                                    break;

-                                case 'L':

-                                    while (desc.charAt(j) != ';') {

-                                        ++j;

-                                    }

-                                    frameLocal[local++] = desc.substring(k + 1,

-                                            j++);

-                                    break;

-                                default:

-                                    break loop;

-                            }

-                        }

-                        frameLocalCount = local;

-                    }

-                    /*

-                     * for the first explicit frame the offset is not

-                     * offset_delta + 1 but only offset_delta; setting the

-                     * implicit frame offset to -1 allow the use of the

-                     * "offset_delta + 1" rule in all cases

-                     */

-                    frameOffset = -1;

-                }

-                v = codeStart;

-                Label l;

-                while (v < codeEnd) {

-                    w = v - codeStart;

-

-                    l = labels[w];

-                    if (l != null) {

-                        mv.visitLabel(l);

-                        if (!skipDebug && l.line > 0) {

-                            mv.visitLineNumber(l.line, l);

-                        }

-                    }

-

-                    while (FRAMES && frameLocal != null

-                            && (frameOffset == w || frameOffset == -1))

-                    {

-                        // if there is a frame for this offset,

-                        // makes the visitor visit it,

-                        // and reads the next frame if there is one.

-                        if (!zip || unzip) {

-                            mv.visitFrame(Opcodes.F_NEW,

-                                    frameLocalCount,

-                                    frameLocal,

-                                    frameStackCount,

-                                    frameStack);

-                        } else if (frameOffset != -1) {

-                            mv.visitFrame(frameMode,

-                                    frameLocalDiff,

-                                    frameLocal,

-                                    frameStackCount,

-                                    frameStack);

-                        }

-

-                        if (frameCount > 0) {

-                            int tag, delta, n;

-                            if (zip) {

-                                tag = b[stackMap++] & 0xFF;

-                            } else {

-                                tag = MethodWriter.FULL_FRAME;

-                                frameOffset = -1;

-                            }

-                            frameLocalDiff = 0;

-                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)

-                            {

-                                delta = tag;

-                                frameMode = Opcodes.F_SAME;

-                                frameStackCount = 0;

-                            } else if (tag < MethodWriter.RESERVED) {

-                                delta = tag

-                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;

-                                stackMap = readFrameType(frameStack,

-                                        0,

-                                        stackMap,

-                                        c,

-                                        labels);

-                                frameMode = Opcodes.F_SAME1;

-                                frameStackCount = 1;

-                            } else {

-                                delta = readUnsignedShort(stackMap);

-                                stackMap += 2;

-                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)

-                                {

-                                    stackMap = readFrameType(frameStack,

-                                            0,

-                                            stackMap,

-                                            c,

-                                            labels);

-                                    frameMode = Opcodes.F_SAME1;

-                                    frameStackCount = 1;

-                                } else if (tag >= MethodWriter.CHOP_FRAME

-                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)

-                                {

-                                    frameMode = Opcodes.F_CHOP;

-                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED

-                                            - tag;

-                                    frameLocalCount -= frameLocalDiff;

-                                    frameStackCount = 0;

-                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)

-                                {

-                                    frameMode = Opcodes.F_SAME;

-                                    frameStackCount = 0;

-                                } else if (tag < MethodWriter.FULL_FRAME) {

-                                    j = unzip ? frameLocalCount : 0;

-                                    for (k = tag

-                                            - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)

-                                    {

-                                        stackMap = readFrameType(frameLocal,

-                                                j++,

-                                                stackMap,

-                                                c,

-                                                labels);

-                                    }

-                                    frameMode = Opcodes.F_APPEND;

-                                    frameLocalDiff = tag

-                                            - MethodWriter.SAME_FRAME_EXTENDED;

-                                    frameLocalCount += frameLocalDiff;

-                                    frameStackCount = 0;

-                                } else { // if (tag == FULL_FRAME) {

-                                    frameMode = Opcodes.F_FULL;

-                                    n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);

-                                    stackMap += 2;

-                                    for (j = 0; n > 0; n--) {

-                                        stackMap = readFrameType(frameLocal,

-                                                j++,

-                                                stackMap,

-                                                c,

-                                                labels);

-                                    }

-                                    n = frameStackCount = readUnsignedShort(stackMap);

-                                    stackMap += 2;

-                                    for (j = 0; n > 0; n--) {

-                                        stackMap = readFrameType(frameStack,

-                                                j++,

-                                                stackMap,

-                                                c,

-                                                labels);

-                                    }

-                                }

-                            }

-                            frameOffset += delta + 1;

-                            readLabel(frameOffset, labels);

-

-                            --frameCount;

-                        } else {

-                            frameLocal = null;

-                        }

-                    }

-

-                    int opcode = b[v] & 0xFF;

-                    switch (ClassWriter.TYPE[opcode]) {

-                        case ClassWriter.NOARG_INSN:

-                            mv.visitInsn(opcode);

-                            v += 1;

-                            break;

-                        case ClassWriter.IMPLVAR_INSN:

-                            if (opcode > Opcodes.ISTORE) {

-                                opcode -= 59; // ISTORE_0

-                                mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),

-                                        opcode & 0x3);

-                            } else {

-                                opcode -= 26; // ILOAD_0

-                                mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),

-                                        opcode & 0x3);

-                            }

-                            v += 1;

-                            break;

-                        case ClassWriter.LABEL_INSN:

-                            mv.visitJumpInsn(opcode, labels[w

-                                    + readShort(v + 1)]);

-                            v += 3;

-                            break;

-                        case ClassWriter.LABELW_INSN:

-                            mv.visitJumpInsn(opcode - 33, labels[w

-                                    + readInt(v + 1)]);

-                            v += 5;

-                            break;

-                        case ClassWriter.WIDE_INSN:

-                            opcode = b[v + 1] & 0xFF;

-                            if (opcode == Opcodes.IINC) {

-                                mv.visitIincInsn(readUnsignedShort(v + 2),

-                                        readShort(v + 4));

-                                v += 6;

-                            } else {

-                                mv.visitVarInsn(opcode,

-                                        readUnsignedShort(v + 2));

-                                v += 4;

-                            }

-                            break;

-                        case ClassWriter.TABL_INSN:

-                            // skips 0 to 3 padding bytes

-                            v = v + 4 - (w & 3);

-                            // reads instruction

-                            label = w + readInt(v);

-                            int min = readInt(v + 4);

-                            int max = readInt(v + 8);

-                            v += 12;

-                            Label[] table = new Label[max - min + 1];

-                            for (j = 0; j < table.length; ++j) {

-                                table[j] = labels[w + readInt(v)];

-                                v += 4;

-                            }

-                            mv.visitTableSwitchInsn(min,

-                                    max,

-                                    labels[label],

-                                    table);

-                            break;

-                        case ClassWriter.LOOK_INSN:

-                            // skips 0 to 3 padding bytes

-                            v = v + 4 - (w & 3);

-                            // reads instruction

-                            label = w + readInt(v);

-                            j = readInt(v + 4);

-                            v += 8;

-                            int[] keys = new int[j];

-                            Label[] values = new Label[j];

-                            for (j = 0; j < keys.length; ++j) {

-                                keys[j] = readInt(v);

-                                values[j] = labels[w + readInt(v + 4)];

-                                v += 8;

-                            }

-                            mv.visitLookupSwitchInsn(labels[label],

-                                    keys,

-                                    values);

-                            break;

-                        case ClassWriter.VAR_INSN:

-                            mv.visitVarInsn(opcode, b[v + 1] & 0xFF);

-                            v += 2;

-                            break;

-                        case ClassWriter.SBYTE_INSN:

-                            mv.visitIntInsn(opcode, b[v + 1]);

-                            v += 2;

-                            break;

-                        case ClassWriter.SHORT_INSN:

-                            mv.visitIntInsn(opcode, readShort(v + 1));

-                            v += 3;

-                            break;

-                        case ClassWriter.LDC_INSN:

-                            mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));

-                            v += 2;

-                            break;

-                        case ClassWriter.LDCW_INSN:

-                            mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),

-                                    c));

-                            v += 3;

-                            break;

-                        case ClassWriter.FIELDORMETH_INSN:

-                        case ClassWriter.ITFMETH_INSN:

-                            int cpIndex = items[readUnsignedShort(v + 1)];

-                            String iowner = readClass(cpIndex, c);

-                            cpIndex = items[readUnsignedShort(cpIndex + 2)];

-                            String iname = readUTF8(cpIndex, c);

-                            String idesc = readUTF8(cpIndex + 2, c);

-                            if (opcode < Opcodes.INVOKEVIRTUAL) {

-                                mv.visitFieldInsn(opcode, iowner, iname, idesc);

-                            } else {

-                                mv.visitMethodInsn(opcode, iowner, iname, idesc);

-                            }

-                            if (opcode == Opcodes.INVOKEINTERFACE) {

-                                v += 5;

-                            } else {

-                                v += 3;

-                            }

-                            break;

-                        case ClassWriter.TYPE_INSN:

-                            mv.visitTypeInsn(opcode, readClass(v + 1, c));

-                            v += 3;

-                            break;

-                        case ClassWriter.IINC_INSN:

-                            mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);

-                            v += 3;

-                            break;

-                        // case MANA_INSN:

-                        default:

-                            mv.visitMultiANewArrayInsn(readClass(v + 1, c),

-                                    b[v + 3] & 0xFF);

-                            v += 4;

-                            break;

-                    }

-                }

-                l = labels[codeEnd - codeStart];

-                if (l != null) {

-                    mv.visitLabel(l);

-                }

-                // visits the local variable tables

-                if (!skipDebug && varTable != 0) {

-                    int[] typeTable = null;

-                    if (varTypeTable != 0) {

-                        k = readUnsignedShort(varTypeTable) * 3;

-                        w = varTypeTable + 2;

-                        typeTable = new int[k];

-                        while (k > 0) {

-                            typeTable[--k] = w + 6; // signature

-                            typeTable[--k] = readUnsignedShort(w + 8); // index

-                            typeTable[--k] = readUnsignedShort(w); // start

-                            w += 10;

-                        }

-                    }

-                    k = readUnsignedShort(varTable);

-                    w = varTable + 2;

-                    for (; k > 0; --k) {

-                        int start = readUnsignedShort(w);

-                        int length = readUnsignedShort(w + 2);

-                        int index = readUnsignedShort(w + 8);

-                        String vsignature = null;

-                        if (typeTable != null) {

-                            for (int a = 0; a < typeTable.length; a += 3) {

-                                if (typeTable[a] == start

-                                        && typeTable[a + 1] == index)

-                                {

-                                    vsignature = readUTF8(typeTable[a + 2], c);

-                                    break;

-                                }

-                            }

-                        }

-                        mv.visitLocalVariable(readUTF8(w + 4, c),

-                                readUTF8(w + 6, c),

-                                vsignature,

-                                labels[start],

-                                labels[start + length],

-                                index);

-                        w += 10;

-                    }

-                }

-                // visits the other attributes

-                while (cattrs != null) {

-                    attr = cattrs.next;

-                    cattrs.next = null;

-                    mv.visitAttribute(cattrs);

-                    cattrs = attr;

-                }

-                // visits the max stack and max locals values

-                mv.visitMaxs(maxStack, maxLocals);

-            }

-

-            if (mv != null) {

-                mv.visitEnd();

-            }

-        }

-

-        // visits the end of the class

-        classVisitor.visitEnd();

-    }

-

-    /**

-     * Reads parameter annotations and makes the given visitor visit them.

-     * 

-     * @param v start offset in {@link #b b} of the annotations to be read.

-     * @param desc the method descriptor.

-     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},

-     *        {@link #readClass(int,char[]) readClass} or

-     *        {@link #readConst readConst}.

-     * @param visible <tt>true</tt> if the annotations to be read are visible

-     *        at runtime.

-     * @param mv the visitor that must visit the annotations.

-     */

-    private void readParameterAnnotations(

-        int v,

-        final String desc,

-        final char[] buf,

-        final boolean visible,

-        final MethodVisitor mv)

-    {

-        int i;

-        int n = b[v++] & 0xFF;

-        // workaround for a bug in javac (javac compiler generates a parameter

-        // annotation array whose size is equal to the number of parameters in

-        // the Java source file, while it should generate an array whose size is

-        // equal to the number of parameters in the method descriptor - which

-        // includes the synthetic parameters added by the compiler). This work-

-        // around supposes that the synthetic parameters are the first ones.

-        int synthetics = Type.getArgumentTypes(desc).length - n;

-        AnnotationVisitor av;

-        for (i = 0; i < synthetics; ++i) {

-            // virtual annotation to detect synthetic parameters in MethodWriter 

-            av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);

-            if (av != null) {

-                av.visitEnd();

-            }

-        }

-        for (; i < n + synthetics; ++i) {

-            int j = readUnsignedShort(v);

-            v += 2;

-            for (; j > 0; --j) {

-                av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);

-                v = readAnnotationValues(v + 2, buf, true, av);

-            }

-        }

-    }

-

-    /**

-     * Reads the values of an annotation and makes the given visitor visit them.

-     * 

-     * @param v the start offset in {@link #b b} of the values to be read

-     *        (including the unsigned short that gives the number of values).

-     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},

-     *        {@link #readClass(int,char[]) readClass} or

-     *        {@link #readConst readConst}.

-     * @param named if the annotation values are named or not.

-     * @param av the visitor that must visit the values.

-     * @return the end offset of the annotation values.

-     */

-    private int readAnnotationValues(

-        int v,

-        final char[] buf,

-        final boolean named,

-        final AnnotationVisitor av)

-    {

-        int i = readUnsignedShort(v);

-        v += 2;

-        if (named) {

-            for (; i > 0; --i) {

-                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);

-            }

-        } else {

-            for (; i > 0; --i) {

-                v = readAnnotationValue(v, buf, null, av);

-            }

-        }

-        if (av != null) {

-            av.visitEnd();

-        }

-        return v;

-    }

-

-    /**

-     * Reads a value of an annotation and makes the given visitor visit it.

-     * 

-     * @param v the start offset in {@link #b b} of the value to be read (<i>not

-     *        including the value name constant pool index</i>).

-     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},

-     *        {@link #readClass(int,char[]) readClass} or

-     *        {@link #readConst readConst}.

-     * @param name the name of the value to be read.

-     * @param av the visitor that must visit the value.

-     * @return the end offset of the annotation value.

-     */

-    private int readAnnotationValue(

-        int v,

-        final char[] buf,

-        final String name,

-        final AnnotationVisitor av)

-    {

-        int i;

-        if (av == null) {

-            switch (b[v] & 0xFF) {

-                case 'e': // enum_const_value

-                    return v + 5;

-                case '@': // annotation_value

-                    return readAnnotationValues(v + 3, buf, true, null);

-                case '[': // array_value

-                    return readAnnotationValues(v + 1, buf, false, null);

-                default:

-                    return v + 3;

-            }

-        }

-        switch (b[v++] & 0xFF) {

-            case 'I': // pointer to CONSTANT_Integer

-            case 'J': // pointer to CONSTANT_Long

-            case 'F': // pointer to CONSTANT_Float

-            case 'D': // pointer to CONSTANT_Double

-                av.visit(name, readConst(readUnsignedShort(v), buf));

-                v += 2;

-                break;

-            case 'B': // pointer to CONSTANT_Byte

-                av.visit(name,

-                        new Byte((byte) readInt(items[readUnsignedShort(v)])));

-                v += 2;

-                break;

-            case 'Z': // pointer to CONSTANT_Boolean

-                av.visit(name, readInt(items[readUnsignedShort(v)]) == 0

-                        ? Boolean.FALSE

-                        : Boolean.TRUE);

-                v += 2;

-                break;

-            case 'S': // pointer to CONSTANT_Short

-                av.visit(name,

-                        new Short((short) readInt(items[readUnsignedShort(v)])));

-                v += 2;

-                break;

-            case 'C': // pointer to CONSTANT_Char

-                av.visit(name,

-                        new Character((char) readInt(items[readUnsignedShort(v)])));

-                v += 2;

-                break;

-            case 's': // pointer to CONSTANT_Utf8

-                av.visit(name, readUTF8(v, buf));

-                v += 2;

-                break;

-            case 'e': // enum_const_value

-                av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));

-                v += 4;

-                break;

-            case 'c': // class_info

-                av.visit(name, Type.getType(readUTF8(v, buf)));

-                v += 2;

-                break;

-            case '@': // annotation_value

-                v = readAnnotationValues(v + 2,

-                        buf,

-                        true,

-                        av.visitAnnotation(name, readUTF8(v, buf)));

-                break;

-            case '[': // array_value

-                int size = readUnsignedShort(v);

-                v += 2;

-                if (size == 0) {

-                    return readAnnotationValues(v - 2,

-                            buf,

-                            false,

-                            av.visitArray(name));

-                }

-                switch (this.b[v++] & 0xFF) {

-                    case 'B':

-                        byte[] bv = new byte[size];

-                        for (i = 0; i < size; i++) {

-                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);

-                            v += 3;

-                        }

-                        av.visit(name, bv);

-                        --v;

-                        break;

-                    case 'Z':

-                        boolean[] zv = new boolean[size];

-                        for (i = 0; i < size; i++) {

-                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;

-                            v += 3;

-                        }

-                        av.visit(name, zv);

-                        --v;

-                        break;

-                    case 'S':

-                        short[] sv = new short[size];

-                        for (i = 0; i < size; i++) {

-                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);

-                            v += 3;

-                        }

-                        av.visit(name, sv);

-                        --v;

-                        break;

-                    case 'C':

-                        char[] cv = new char[size];

-                        for (i = 0; i < size; i++) {

-                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);

-                            v += 3;

-                        }

-                        av.visit(name, cv);

-                        --v;

-                        break;

-                    case 'I':

-                        int[] iv = new int[size];

-                        for (i = 0; i < size; i++) {

-                            iv[i] = readInt(items[readUnsignedShort(v)]);

-                            v += 3;

-                        }

-                        av.visit(name, iv);

-                        --v;

-                        break;

-                    case 'J':

-                        long[] lv = new long[size];

-                        for (i = 0; i < size; i++) {

-                            lv[i] = readLong(items[readUnsignedShort(v)]);

-                            v += 3;

-                        }

-                        av.visit(name, lv);

-                        --v;

-                        break;

-                    case 'F':

-                        float[] fv = new float[size];

-                        for (i = 0; i < size; i++) {

-                            fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));

-                            v += 3;

-                        }

-                        av.visit(name, fv);

-                        --v;

-                        break;

-                    case 'D':

-                        double[] dv = new double[size];

-                        for (i = 0; i < size; i++) {

-                            dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));

-                            v += 3;

-                        }

-                        av.visit(name, dv);

-                        --v;

-                        break;

-                    default:

-                        v = readAnnotationValues(v - 3,

-                                buf,

-                                false,

-                                av.visitArray(name));

-                }

-        }

-        return v;

-    }

-

-    private int readFrameType(

-        final Object[] frame,

-        final int index,

-        int v,

-        final char[] buf,

-        final Label[] labels)

-    {

-        int type = b[v++] & 0xFF;

-        switch (type) {

-            case 0:

-                frame[index] = Opcodes.TOP;

-                break;

-            case 1:

-                frame[index] = Opcodes.INTEGER;

-                break;

-            case 2:

-                frame[index] = Opcodes.FLOAT;

-                break;

-            case 3:

-                frame[index] = Opcodes.DOUBLE;

-                break;

-            case 4:

-                frame[index] = Opcodes.LONG;

-                break;

-            case 5:

-                frame[index] = Opcodes.NULL;

-                break;

-            case 6:

-                frame[index] = Opcodes.UNINITIALIZED_THIS;

-                break;

-            case 7: // Object

-                frame[index] = readClass(v, buf);

-                v += 2;

-                break;

-            default: // Uninitialized

-                frame[index] = readLabel(readUnsignedShort(v), labels);

-                v += 2;

-        }

-        return v;

-    }

-

-    /**

-     * Returns the label corresponding to the given offset. The default

-     * implementation of this method creates a label for the given offset if it

-     * has not been already created.

-     * 

-     * @param offset a bytecode offset in a method.

-     * @param labels the already created labels, indexed by their offset. If a

-     *        label already exists for offset this method must not create a new

-     *        one. Otherwise it must store the new label in this array.

-     * @return a non null Label, which must be equal to labels[offset].

-     */

-    protected Label readLabel(int offset, Label[] labels) {

-        if (labels[offset] == null) {

-            labels[offset] = new Label();

-        }

-        return labels[offset];

-    }

-

-    /**

-     * Reads an attribute in {@link #b b}.

-     * 

-     * @param attrs prototypes of the attributes that must be parsed during the

-     *        visit of the class. Any attribute whose type is not equal to the

-     *        type of one the prototypes is ignored (i.e. an empty

-     *        {@link Attribute} instance is returned).

-     * @param type the type of the attribute.

-     * @param off index of the first byte of the attribute's content in

-     *        {@link #b b}. The 6 attribute header bytes, containing the type

-     *        and the length of the attribute, are not taken into account here

-     *        (they have already been read).

-     * @param len the length of the attribute's content.

-     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},

-     *        {@link #readClass(int,char[]) readClass} or

-     *        {@link #readConst readConst}.

-     * @param codeOff index of the first byte of code's attribute content in

-     *        {@link #b b}, or -1 if the attribute to be read is not a code

-     *        attribute. The 6 attribute header bytes, containing the type and

-     *        the length of the attribute, are not taken into account here.

-     * @param labels the labels of the method's code, or <tt>null</tt> if the

-     *        attribute to be read is not a code attribute.

-     * @return the attribute that has been read, or <tt>null</tt> to skip this

-     *         attribute.

-     */

-    private Attribute readAttribute(

-        final Attribute[] attrs,

-        final String type,

-        final int off,

-        final int len,

-        final char[] buf,

-        final int codeOff,

-        final Label[] labels)

-    {

-        for (int i = 0; i < attrs.length; ++i) {

-            if (attrs[i].type.equals(type)) {

-                return attrs[i].read(this, off, len, buf, codeOff, labels);

-            }

-        }

-        return new Attribute(type).read(this, off, len, null, -1, null);

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods: low level parsing

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the start index of the constant pool item in {@link #b b}, plus

-     * one. <i>This method is intended for {@link Attribute} sub classes, and is

-     * normally not needed by class generators or adapters.</i>

-     * 

-     * @param item the index a constant pool item.

-     * @return the start index of the constant pool item in {@link #b b}, plus

-     *         one.

-     */

-    public int getItem(final int item) {

-        return items[item];

-    }

-

-    /**

-     * Reads a byte value in {@link #b b}. <i>This method is intended for

-     * {@link Attribute} sub classes, and is normally not needed by class

-     * generators or adapters.</i>

-     * 

-     * @param index the start index of the value to be read in {@link #b b}.

-     * @return the read value.

-     */

-    public int readByte(final int index) {

-        return b[index] & 0xFF;

-    }

-

-    /**

-     * Reads an unsigned short value in {@link #b b}. <i>This method is

-     * intended for {@link Attribute} sub classes, and is normally not needed by

-     * class generators or adapters.</i>

-     * 

-     * @param index the start index of the value to be read in {@link #b b}.

-     * @return the read value.

-     */

-    public int readUnsignedShort(final int index) {

-        byte[] b = this.b;

-        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);

-    }

-

-    /**

-     * Reads a signed short value in {@link #b b}. <i>This method is intended

-     * for {@link Attribute} sub classes, and is normally not needed by class

-     * generators or adapters.</i>

-     * 

-     * @param index the start index of the value to be read in {@link #b b}.

-     * @return the read value.

-     */

-    public short readShort(final int index) {

-        byte[] b = this.b;

-        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));

-    }

-

-    /**

-     * Reads a signed int value in {@link #b b}. <i>This method is intended for

-     * {@link Attribute} sub classes, and is normally not needed by class

-     * generators or adapters.</i>

-     * 

-     * @param index the start index of the value to be read in {@link #b b}.

-     * @return the read value.

-     */

-    public int readInt(final int index) {

-        byte[] b = this.b;

-        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)

-                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);

-    }

-

-    /**

-     * Reads a signed long value in {@link #b b}. <i>This method is intended

-     * for {@link Attribute} sub classes, and is normally not needed by class

-     * generators or adapters.</i>

-     * 

-     * @param index the start index of the value to be read in {@link #b b}.

-     * @return the read value.

-     */

-    public long readLong(final int index) {

-        long l1 = readInt(index);

-        long l0 = readInt(index + 4) & 0xFFFFFFFFL;

-        return (l1 << 32) | l0;

-    }

-

-    /**

-     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method

-     * is intended for {@link Attribute} sub classes, and is normally not needed

-     * by class generators or adapters.</i>

-     * 

-     * @param index the start index of an unsigned short value in {@link #b b},

-     *        whose value is the index of an UTF8 constant pool item.

-     * @param buf buffer to be used to read the item. This buffer must be

-     *        sufficiently large. It is not automatically resized.

-     * @return the String corresponding to the specified UTF8 item.

-     */

-    public String readUTF8(int index, final char[] buf) {

-        int item = readUnsignedShort(index);

-        String s = strings[item];

-        if (s != null) {

-            return s;

-        }

-        index = items[item];

-        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);

-    }

-

-    /**

-     * Reads UTF8 string in {@link #b b}.

-     * 

-     * @param index start offset of the UTF8 string to be read.

-     * @param utfLen length of the UTF8 string to be read.

-     * @param buf buffer to be used to read the string. This buffer must be

-     *        sufficiently large. It is not automatically resized.

-     * @return the String corresponding to the specified UTF8 string.

-     */

-    private String readUTF(int index, final int utfLen, final char[] buf) {

-        int endIndex = index + utfLen;

-        byte[] b = this.b;

-        int strLen = 0;

-        int c, d, e;

-        while (index < endIndex) {

-            c = b[index++] & 0xFF;

-            switch (c >> 4) {

-                case 0:

-                case 1:

-                case 2:

-                case 3:

-                case 4:

-                case 5:

-                case 6:

-                case 7:

-                    // 0xxxxxxx

-                    buf[strLen++] = (char) c;

-                    break;

-                case 12:

-                case 13:

-                    // 110x xxxx 10xx xxxx

-                    d = b[index++];

-                    buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));

-                    break;

-                default:

-                    // 1110 xxxx 10xx xxxx 10xx xxxx

-                    d = b[index++];

-                    e = b[index++];

-                    buf[strLen++] = (char) (((c & 0x0F) << 12)

-                            | ((d & 0x3F) << 6) | (e & 0x3F));

-                    break;

-            }

-        }

-        return new String(buf, 0, strLen);

-    }

-

-    /**

-     * Reads a class constant pool item in {@link #b b}. <i>This method is

-     * intended for {@link Attribute} sub classes, and is normally not needed by

-     * class generators or adapters.</i>

-     * 

-     * @param index the start index of an unsigned short value in {@link #b b},

-     *        whose value is the index of a class constant pool item.

-     * @param buf buffer to be used to read the item. This buffer must be

-     *        sufficiently large. It is not automatically resized.

-     * @return the String corresponding to the specified class item.

-     */

-    public String readClass(final int index, final char[] buf) {

-        // computes the start index of the CONSTANT_Class item in b

-        // and reads the CONSTANT_Utf8 item designated by

-        // the first two bytes of this CONSTANT_Class item

-        return readUTF8(items[readUnsignedShort(index)], buf);

-    }

-

-    /**

-     * Reads a numeric or string constant pool item in {@link #b b}. <i>This

-     * method is intended for {@link Attribute} sub classes, and is normally not

-     * needed by class generators or adapters.</i>

-     * 

-     * @param item the index of a constant pool item.

-     * @param buf buffer to be used to read the item. This buffer must be

-     *        sufficiently large. It is not automatically resized.

-     * @return the {@link Integer}, {@link Float}, {@link Long},

-     *         {@link Double}, {@link String} or {@link Type} corresponding to

-     *         the given constant pool item.

-     */

-    public Object readConst(final int item, final char[] buf) {

-        int index = items[item];

-        switch (b[index - 1]) {

-            case ClassWriter.INT:

-                return new Integer(readInt(index));

-            case ClassWriter.FLOAT:

-                return new Float(Float.intBitsToFloat(readInt(index)));

-            case ClassWriter.LONG:

-                return new Long(readLong(index));

-            case ClassWriter.DOUBLE:

-                return new Double(Double.longBitsToDouble(readLong(index)));

-            case ClassWriter.CLASS:

-                return Type.getObjectType(readUTF8(index, buf));

-                // case ClassWriter.STR:

-            default:

-                return readUTF8(index, buf);

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/ClassVisitor.java b/cglib-and-asm/src/org/mockito/asm/ClassVisitor.java
deleted file mode 100644
index 22180bc..0000000
--- a/cglib-and-asm/src/org/mockito/asm/ClassVisitor.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A visitor to visit a Java class. The methods of this interface must be called

- * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [

- * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |

- * <tt>visitAttribute</tt> )* (<tt>visitInnerClass</tt> |

- * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.

- * 

- * @author Eric Bruneton

- */

-public interface ClassVisitor {

-

-    /**

-     * Visits the header of the class.

-     * 

-     * @param version the class version.

-     * @param access the class's access flags (see {@link Opcodes}). This

-     *        parameter also indicates if the class is deprecated.

-     * @param name the internal name of the class (see

-     *        {@link Type#getInternalName() getInternalName}).

-     * @param signature the signature of this class. May be <tt>null</tt> if

-     *        the class is not a generic one, and does not extend or implement

-     *        generic classes or interfaces.

-     * @param superName the internal of name of the super class (see

-     *        {@link Type#getInternalName() getInternalName}). For interfaces,

-     *        the super class is {@link Object}. May be <tt>null</tt>, but

-     *        only for the {@link Object} class.

-     * @param interfaces the internal names of the class's interfaces (see

-     *        {@link Type#getInternalName() getInternalName}). May be

-     *        <tt>null</tt>.

-     */

-    void visit(

-        int version,

-        int access,

-        String name,

-        String signature,

-        String superName,

-        String[] interfaces);

-

-    /**

-     * Visits the source of the class.

-     * 

-     * @param source the name of the source file from which the class was

-     *        compiled. May be <tt>null</tt>.

-     * @param debug additional debug information to compute the correspondance

-     *        between source and compiled elements of the class. May be

-     *        <tt>null</tt>.

-     */

-    void visitSource(String source, String debug);

-

-    /**

-     * Visits the enclosing class of the class. This method must be called only

-     * if the class has an enclosing class.

-     * 

-     * @param owner internal name of the enclosing class of the class.

-     * @param name the name of the method that contains the class, or

-     *        <tt>null</tt> if the class is not enclosed in a method of its

-     *        enclosing class.

-     * @param desc the descriptor of the method that contains the class, or

-     *        <tt>null</tt> if the class is not enclosed in a method of its

-     *        enclosing class.

-     */

-    void visitOuterClass(String owner, String name, String desc);

-

-    /**

-     * Visits an annotation of the class.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values, or <tt>null</tt> if

-     *         this visitor is not interested in visiting this annotation.

-     */

-    AnnotationVisitor visitAnnotation(String desc, boolean visible);

-

-    /**

-     * Visits a non standard attribute of the class.

-     * 

-     * @param attr an attribute.

-     */

-    void visitAttribute(Attribute attr);

-

-    /**

-     * Visits information about an inner class. This inner class is not

-     * necessarily a member of the class being visited.

-     * 

-     * @param name the internal name of an inner class (see

-     *        {@link Type#getInternalName() getInternalName}).

-     * @param outerName the internal name of the class to which the inner class

-     *        belongs (see {@link Type#getInternalName() getInternalName}). May

-     *        be <tt>null</tt> for not member classes.

-     * @param innerName the (simple) name of the inner class inside its

-     *        enclosing class. May be <tt>null</tt> for anonymous inner

-     *        classes.

-     * @param access the access flags of the inner class as originally declared

-     *        in the enclosing class.

-     */

-    void visitInnerClass(

-        String name,

-        String outerName,

-        String innerName,

-        int access);

-

-    /**

-     * Visits a field of the class.

-     * 

-     * @param access the field's access flags (see {@link Opcodes}). This

-     *        parameter also indicates if the field is synthetic and/or

-     *        deprecated.

-     * @param name the field's name.

-     * @param desc the field's descriptor (see {@link Type Type}).

-     * @param signature the field's signature. May be <tt>null</tt> if the

-     *        field's type does not use generic types.

-     * @param value the field's initial value. This parameter, which may be

-     *        <tt>null</tt> if the field does not have an initial value, must

-     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a

-     *        {@link Double} or a {@link String} (for <tt>int</tt>,

-     *        <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields

-     *        respectively). <i>This parameter is only used for static fields</i>.

-     *        Its value is ignored for non static fields, which must be

-     *        initialized through bytecode instructions in constructors or

-     *        methods.

-     * @return a visitor to visit field annotations and attributes, or

-     *         <tt>null</tt> if this class visitor is not interested in

-     *         visiting these annotations and attributes.

-     */

-    FieldVisitor visitField(

-        int access,

-        String name,

-        String desc,

-        String signature,

-        Object value);

-

-    /**

-     * Visits a method of the class. This method <i>must</i> return a new

-     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is

-     * called, i.e., it should not return a previously returned visitor.

-     * 

-     * @param access the method's access flags (see {@link Opcodes}). This

-     *        parameter also indicates if the method is synthetic and/or

-     *        deprecated.

-     * @param name the method's name.

-     * @param desc the method's descriptor (see {@link Type Type}).

-     * @param signature the method's signature. May be <tt>null</tt> if the

-     *        method parameters, return type and exceptions do not use generic

-     *        types.

-     * @param exceptions the internal names of the method's exception classes

-     *        (see {@link Type#getInternalName() getInternalName}). May be

-     *        <tt>null</tt>.

-     * @return an object to visit the byte code of the method, or <tt>null</tt>

-     *         if this class visitor is not interested in visiting the code of

-     *         this method.

-     */

-    MethodVisitor visitMethod(

-        int access,

-        String name,

-        String desc,

-        String signature,

-        String[] exceptions);

-

-    /**

-     * Visits the end of the class. This method, which is the last one to be

-     * called, is used to inform the visitor that all the fields and methods of

-     * the class have been visited.

-     */

-    void visitEnd();

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/ClassWriter.java b/cglib-and-asm/src/org/mockito/asm/ClassWriter.java
deleted file mode 100644
index 366f568..0000000
--- a/cglib-and-asm/src/org/mockito/asm/ClassWriter.java
+++ /dev/null
@@ -1,1344 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A {@link ClassVisitor} that generates classes in bytecode form. More

- * precisely this visitor generates a byte array conforming to the Java class

- * file format. It can be used alone, to generate a Java class "from scratch",

- * or with one or more {@link ClassReader ClassReader} and adapter class visitor

- * to generate a modified class from one or more existing Java classes.

- *

- * @author Eric Bruneton

- */

-public class ClassWriter implements ClassVisitor {

-

-    /**

-     * Flag to automatically compute the maximum stack size and the maximum

-     * number of local variables of methods. If this flag is set, then the

-     * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the

-     * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}

-     * method will be ignored, and computed automatically from the signature and

-     * the bytecode of each method.

-     *

-     * @see #ClassWriter(int)

-     */

-    public static final int COMPUTE_MAXS = 1;

-

-    /**

-     * Flag to automatically compute the stack map frames of methods from

-     * scratch. If this flag is set, then the calls to the

-     * {@link MethodVisitor#visitFrame} method are ignored, and the stack map

-     * frames are recomputed from the methods bytecode. The arguments of the

-     * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and

-     * recomputed from the bytecode. In other words, computeFrames implies

-     * computeMaxs.

-     *

-     * @see #ClassWriter(int)

-     */

-    public static final int COMPUTE_FRAMES = 2;

-

-    /**

-     * The type of instructions without any argument.

-     */

-    static final int NOARG_INSN = 0;

-

-    /**

-     * The type of instructions with an signed byte argument.

-     */

-    static final int SBYTE_INSN = 1;

-

-    /**

-     * The type of instructions with an signed short argument.

-     */

-    static final int SHORT_INSN = 2;

-

-    /**

-     * The type of instructions with a local variable index argument.

-     */

-    static final int VAR_INSN = 3;

-

-    /**

-     * The type of instructions with an implicit local variable index argument.

-     */

-    static final int IMPLVAR_INSN = 4;

-

-    /**

-     * The type of instructions with a type descriptor argument.

-     */

-    static final int TYPE_INSN = 5;

-

-    /**

-     * The type of field and method invocations instructions.

-     */

-    static final int FIELDORMETH_INSN = 6;

-

-    /**

-     * The type of the INVOKEINTERFACE instruction.

-     */

-    static final int ITFMETH_INSN = 7;

-

-    /**

-     * The type of instructions with a 2 bytes bytecode offset label.

-     */

-    static final int LABEL_INSN = 8;

-

-    /**

-     * The type of instructions with a 4 bytes bytecode offset label.

-     */

-    static final int LABELW_INSN = 9;

-

-    /**

-     * The type of the LDC instruction.

-     */

-    static final int LDC_INSN = 10;

-

-    /**

-     * The type of the LDC_W and LDC2_W instructions.

-     */

-    static final int LDCW_INSN = 11;

-

-    /**

-     * The type of the IINC instruction.

-     */

-    static final int IINC_INSN = 12;

-

-    /**

-     * The type of the TABLESWITCH instruction.

-     */

-    static final int TABL_INSN = 13;

-

-    /**

-     * The type of the LOOKUPSWITCH instruction.

-     */

-    static final int LOOK_INSN = 14;

-

-    /**

-     * The type of the MULTIANEWARRAY instruction.

-     */

-    static final int MANA_INSN = 15;

-

-    /**

-     * The type of the WIDE instruction.

-     */

-    static final int WIDE_INSN = 16;

-

-    /**

-     * The instruction types of all JVM opcodes.

-     */

-    static final byte[] TYPE;

-

-    /**

-     * The type of CONSTANT_Class constant pool items.

-     */

-    static final int CLASS = 7;

-

-    /**

-     * The type of CONSTANT_Fieldref constant pool items.

-     */

-    static final int FIELD = 9;

-

-    /**

-     * The type of CONSTANT_Methodref constant pool items.

-     */

-    static final int METH = 10;

-

-    /**

-     * The type of CONSTANT_InterfaceMethodref constant pool items.

-     */

-    static final int IMETH = 11;

-

-    /**

-     * The type of CONSTANT_String constant pool items.

-     */

-    static final int STR = 8;

-

-    /**

-     * The type of CONSTANT_Integer constant pool items.

-     */

-    static final int INT = 3;

-

-    /**

-     * The type of CONSTANT_Float constant pool items.

-     */

-    static final int FLOAT = 4;

-

-    /**

-     * The type of CONSTANT_Long constant pool items.

-     */

-    static final int LONG = 5;

-

-    /**

-     * The type of CONSTANT_Double constant pool items.

-     */

-    static final int DOUBLE = 6;

-

-    /**

-     * The type of CONSTANT_NameAndType constant pool items.

-     */

-    static final int NAME_TYPE = 12;

-

-    /**

-     * The type of CONSTANT_Utf8 constant pool items.

-     */

-    static final int UTF8 = 1;

-

-    /**

-     * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},

-     * instead of the constant pool, in order to avoid clashes with normal

-     * constant pool items in the ClassWriter constant pool's hash table.

-     */

-    static final int TYPE_NORMAL = 13;

-

-    /**

-     * Uninitialized type Item stored in the ClassWriter

-     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to

-     * avoid clashes with normal constant pool items in the ClassWriter constant

-     * pool's hash table.

-     */

-    static final int TYPE_UNINIT = 14;

-

-    /**

-     * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},

-     * instead of the constant pool, in order to avoid clashes with normal

-     * constant pool items in the ClassWriter constant pool's hash table.

-     */

-    static final int TYPE_MERGED = 15;

-

-    /**

-     * The class reader from which this class writer was constructed, if any.

-     */

-    ClassReader cr;

-

-    /**

-     * Minor and major version numbers of the class to be generated.

-     */

-    int version;

-

-    /**

-     * Index of the next item to be added in the constant pool.

-     */

-    int index;

-

-    /**

-     * The constant pool of this class.

-     */

-    final ByteVector pool;

-

-    /**

-     * The constant pool's hash table data.

-     */

-    Item[] items;

-

-    /**

-     * The threshold of the constant pool's hash table.

-     */

-    int threshold;

-

-    /**

-     * A reusable key used to look for items in the {@link #items} hash table.

-     */

-    final Item key;

-

-    /**

-     * A reusable key used to look for items in the {@link #items} hash table.

-     */

-    final Item key2;

-

-    /**

-     * A reusable key used to look for items in the {@link #items} hash table.

-     */

-    final Item key3;

-

-    /**

-     * A type table used to temporarily store internal names that will not

-     * necessarily be stored in the constant pool. This type table is used by

-     * the control flow and data flow analysis algorithm used to compute stack

-     * map frames from scratch. This array associates to each index <tt>i</tt>

-     * the Item whose index is <tt>i</tt>. All Item objects stored in this

-     * array are also stored in the {@link #items} hash table. These two arrays

-     * allow to retrieve an Item from its index or, conversely, to get the index

-     * of an Item from its value. Each Item stores an internal name in its

-     * {@link Item#strVal1} field.

-     */

-    Item[] typeTable;

-

-    /**

-     * Number of elements in the {@link #typeTable} array.

-     */

-    private short typeCount;

-

-    /**

-     * The access flags of this class.

-     */

-    private int access;

-

-    /**

-     * The constant pool item that contains the internal name of this class.

-     */

-    private int name;

-

-    /**

-     * The internal name of this class.

-     */

-    String thisName;

-

-    /**

-     * The constant pool item that contains the signature of this class.

-     */

-    private int signature;

-

-    /**

-     * The constant pool item that contains the internal name of the super class

-     * of this class.

-     */

-    private int superName;

-

-    /**

-     * Number of interfaces implemented or extended by this class or interface.

-     */

-    private int interfaceCount;

-

-    /**

-     * The interfaces implemented or extended by this class or interface. More

-     * precisely, this array contains the indexes of the constant pool items

-     * that contain the internal names of these interfaces.

-     */

-    private int[] interfaces;

-

-    /**

-     * The index of the constant pool item that contains the name of the source

-     * file from which this class was compiled.

-     */

-    private int sourceFile;

-

-    /**

-     * The SourceDebug attribute of this class.

-     */

-    private ByteVector sourceDebug;

-

-    /**

-     * The constant pool item that contains the name of the enclosing class of

-     * this class.

-     */

-    private int enclosingMethodOwner;

-

-    /**

-     * The constant pool item that contains the name and descriptor of the

-     * enclosing method of this class.

-     */

-    private int enclosingMethod;

-

-    /**

-     * The runtime visible annotations of this class.

-     */

-    private AnnotationWriter anns;

-

-    /**

-     * The runtime invisible annotations of this class.

-     */

-    private AnnotationWriter ianns;

-

-    /**

-     * The non standard attributes of this class.

-     */

-    private Attribute attrs;

-

-    /**

-     * The number of entries in the InnerClasses attribute.

-     */

-    private int innerClassesCount;

-

-    /**

-     * The InnerClasses attribute.

-     */

-    private ByteVector innerClasses;

-

-    /**

-     * The fields of this class. These fields are stored in a linked list of

-     * {@link FieldWriter} objects, linked to each other by their

-     * {@link FieldWriter#next} field. This field stores the first element of

-     * this list.

-     */

-    FieldWriter firstField;

-

-    /**

-     * The fields of this class. These fields are stored in a linked list of

-     * {@link FieldWriter} objects, linked to each other by their

-     * {@link FieldWriter#next} field. This field stores the last element of

-     * this list.

-     */

-    FieldWriter lastField;

-

-    /**

-     * The methods of this class. These methods are stored in a linked list of

-     * {@link MethodWriter} objects, linked to each other by their

-     * {@link MethodWriter#next} field. This field stores the first element of

-     * this list.

-     */

-    MethodWriter firstMethod;

-

-    /**

-     * The methods of this class. These methods are stored in a linked list of

-     * {@link MethodWriter} objects, linked to each other by their

-     * {@link MethodWriter#next} field. This field stores the last element of

-     * this list.

-     */

-    MethodWriter lastMethod;

-

-    /**

-     * <tt>true</tt> if the maximum stack size and number of local variables

-     * must be automatically computed.

-     */

-    private final boolean computeMaxs;

-

-    /**

-     * <tt>true</tt> if the stack map frames must be recomputed from scratch.

-     */

-    private final boolean computeFrames;

-

-    /**

-     * <tt>true</tt> if the stack map tables of this class are invalid. The

-     * {@link MethodWriter#resizeInstructions} method cannot transform existing

-     * stack map tables, and so produces potentially invalid classes when it is

-     * executed. In this case the class is reread and rewritten with the

-     * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize

-     * stack map tables when this option is used).

-     */

-    boolean invalidFrames;

-

-    // ------------------------------------------------------------------------

-    // Static initializer

-    // ------------------------------------------------------------------------

-

-    /**

-     * Computes the instruction types of JVM opcodes.

-     */

-    static {

-        int i;

-        byte[] b = new byte[220];

-        String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"

-                + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

-                + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"

-                + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";

-        for (i = 0; i < b.length; ++i) {

-            b[i] = (byte) (s.charAt(i) - 'A');

-        }

-        TYPE = b;

-

-        // code to generate the above string

-        //

-        // // SBYTE_INSN instructions

-        // b[Constants.NEWARRAY] = SBYTE_INSN;

-        // b[Constants.BIPUSH] = SBYTE_INSN;

-        //

-        // // SHORT_INSN instructions

-        // b[Constants.SIPUSH] = SHORT_INSN;

-        //

-        // // (IMPL)VAR_INSN instructions

-        // b[Constants.RET] = VAR_INSN;

-        // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {

-        // b[i] = VAR_INSN;

-        // }

-        // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {

-        // b[i] = VAR_INSN;

-        // }

-        // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3

-        // b[i] = IMPLVAR_INSN;

-        // }

-        // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3

-        // b[i] = IMPLVAR_INSN;

-        // }

-        //

-        // // TYPE_INSN instructions

-        // b[Constants.NEW] = TYPE_INSN;

-        // b[Constants.ANEWARRAY] = TYPE_INSN;

-        // b[Constants.CHECKCAST] = TYPE_INSN;

-        // b[Constants.INSTANCEOF] = TYPE_INSN;

-        //

-        // // (Set)FIELDORMETH_INSN instructions

-        // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {

-        // b[i] = FIELDORMETH_INSN;

-        // }

-        // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;

-        //

-        // // LABEL(W)_INSN instructions

-        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {

-        // b[i] = LABEL_INSN;

-        // }

-        // b[Constants.IFNULL] = LABEL_INSN;

-        // b[Constants.IFNONNULL] = LABEL_INSN;

-        // b[200] = LABELW_INSN; // GOTO_W

-        // b[201] = LABELW_INSN; // JSR_W

-        // // temporary opcodes used internally by ASM - see Label and

-        // MethodWriter

-        // for (i = 202; i < 220; ++i) {

-        // b[i] = LABEL_INSN;

-        // }

-        //

-        // // LDC(_W) instructions

-        // b[Constants.LDC] = LDC_INSN;

-        // b[19] = LDCW_INSN; // LDC_W

-        // b[20] = LDCW_INSN; // LDC2_W

-        //

-        // // special instructions

-        // b[Constants.IINC] = IINC_INSN;

-        // b[Constants.TABLESWITCH] = TABL_INSN;

-        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;

-        // b[Constants.MULTIANEWARRAY] = MANA_INSN;

-        // b[196] = WIDE_INSN; // WIDE

-        //

-        // for (i = 0; i < b.length; ++i) {

-        // System.err.print((char)('A' + b[i]));

-        // }

-        // System.err.println();

-    }

-

-    // ------------------------------------------------------------------------

-    // Constructor

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a new {@link ClassWriter} object.

-     *

-     * @param flags option flags that can be used to modify the default behavior

-     *        of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.

-     */

-    public ClassWriter(final int flags) {

-        index = 1;

-        pool = new ByteVector();

-        items = new Item[256];

-        threshold = (int) (0.75d * items.length);

-        key = new Item();

-        key2 = new Item();

-        key3 = new Item();

-        this.computeMaxs = (flags & COMPUTE_MAXS) != 0;

-        this.computeFrames = (flags & COMPUTE_FRAMES) != 0;

-    }

-

-    /**

-     * Constructs a new {@link ClassWriter} object and enables optimizations for

-     * "mostly add" bytecode transformations. These optimizations are the

-     * following:

-     *

-     * <ul> <li>The constant pool from the original class is copied as is in

-     * the new class, which saves time. New constant pool entries will be added

-     * at the end if necessary, but unused constant pool entries <i>won't be

-     * removed</i>.</li> <li>Methods that are not transformed are copied as

-     * is in the new class, directly from the original class bytecode (i.e.

-     * without emitting visit events for all the method instructions), which

-     * saves a <i>lot</i> of time. Untransformed methods are detected by the

-     * fact that the {@link ClassReader} receives {@link MethodVisitor} objects

-     * that come from a {@link ClassWriter} (and not from a custom

-     * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>

-     * </ul>

-     *

-     * @param classReader the {@link ClassReader} used to read the original

-     *        class. It will be used to copy the entire constant pool from the

-     *        original class and also to copy other fragments of original

-     *        bytecode where applicable.

-     * @param flags option flags that can be used to modify the default behavior

-     *        of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.

-     */

-    public ClassWriter(final ClassReader classReader, final int flags) {

-        this(flags);

-        classReader.copyPool(this);

-        this.cr = classReader;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the ClassVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(

-        final int version,

-        final int access,

-        final String name,

-        final String signature,

-        final String superName,

-        final String[] interfaces)

-    {

-        this.version = version;

-        this.access = access;

-        this.name = newClass(name);

-        thisName = name;

-        if (ClassReader.SIGNATURES && signature != null) {

-            this.signature = newUTF8(signature);

-        }

-        this.superName = superName == null ? 0 : newClass(superName);

-        if (interfaces != null && interfaces.length > 0) {

-            interfaceCount = interfaces.length;

-            this.interfaces = new int[interfaceCount];

-            for (int i = 0; i < interfaceCount; ++i) {

-                this.interfaces[i] = newClass(interfaces[i]);

-            }

-        }

-    }

-

-    public void visitSource(final String file, final String debug) {

-        if (file != null) {

-            sourceFile = newUTF8(file);

-        }

-        if (debug != null) {

-            sourceDebug = new ByteVector().putUTF8(debug);

-        }

-    }

-

-    public void visitOuterClass(

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        enclosingMethodOwner = newClass(owner);

-        if (name != null && desc != null) {

-            enclosingMethod = newNameType(name, desc);

-        }

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        if (!ClassReader.ANNOTATIONS) {

-            return null;

-        }

-        ByteVector bv = new ByteVector();

-        // write type, and reserve space for values count

-        bv.putShort(newUTF8(desc)).putShort(0);

-        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);

-        if (visible) {

-            aw.next = anns;

-            anns = aw;

-        } else {

-            aw.next = ianns;

-            ianns = aw;

-        }

-        return aw;

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        attr.next = attrs;

-        attrs = attr;

-    }

-

-    public void visitInnerClass(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        if (innerClasses == null) {

-            innerClasses = new ByteVector();

-        }

-        ++innerClassesCount;

-        innerClasses.putShort(name == null ? 0 : newClass(name));

-        innerClasses.putShort(outerName == null ? 0 : newClass(outerName));

-        innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));

-        innerClasses.putShort(access);

-    }

-

-    public FieldVisitor visitField(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        return new FieldWriter(this, access, name, desc, signature, value);

-    }

-

-    public MethodVisitor visitMethod(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        return new MethodWriter(this,

-                access,

-                name,

-                desc,

-                signature,

-                exceptions,

-                computeMaxs,

-                computeFrames);

-    }

-

-    public void visitEnd() {

-    }

-

-    // ------------------------------------------------------------------------

-    // Other public methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the bytecode of the class that was build with this class writer.

-     *

-     * @return the bytecode of the class that was build with this class writer.

-     */

-    public byte[] toByteArray() {

-        // computes the real size of the bytecode of this class

-        int size = 24 + 2 * interfaceCount;

-        int nbFields = 0;

-        FieldWriter fb = firstField;

-        while (fb != null) {

-            ++nbFields;

-            size += fb.getSize();

-            fb = fb.next;

-        }

-        int nbMethods = 0;

-        MethodWriter mb = firstMethod;

-        while (mb != null) {

-            ++nbMethods;

-            size += mb.getSize();

-            mb = mb.next;

-        }

-        int attributeCount = 0;

-        if (ClassReader.SIGNATURES && signature != 0) {

-            ++attributeCount;

-            size += 8;

-            newUTF8("Signature");

-        }

-        if (sourceFile != 0) {

-            ++attributeCount;

-            size += 8;

-            newUTF8("SourceFile");

-        }

-        if (sourceDebug != null) {

-            ++attributeCount;

-            size += sourceDebug.length + 4;

-            newUTF8("SourceDebugExtension");

-        }

-        if (enclosingMethodOwner != 0) {

-            ++attributeCount;

-            size += 10;

-            newUTF8("EnclosingMethod");

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            ++attributeCount;

-            size += 6;

-            newUTF8("Deprecated");

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (version & 0xffff) < Opcodes.V1_5)

-        {

-            ++attributeCount;

-            size += 6;

-            newUTF8("Synthetic");

-        }

-        if (innerClasses != null) {

-            ++attributeCount;

-            size += 8 + innerClasses.length;

-            newUTF8("InnerClasses");

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            ++attributeCount;

-            size += 8 + anns.getSize();

-            newUTF8("RuntimeVisibleAnnotations");

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            ++attributeCount;

-            size += 8 + ianns.getSize();

-            newUTF8("RuntimeInvisibleAnnotations");

-        }

-        if (attrs != null) {

-            attributeCount += attrs.getCount();

-            size += attrs.getSize(this, null, 0, -1, -1);

-        }

-        size += pool.length;

-        // allocates a byte vector of this size, in order to avoid unnecessary

-        // arraycopy operations in the ByteVector.enlarge() method

-        ByteVector out = new ByteVector(size);

-        out.putInt(0xCAFEBABE).putInt(version);

-        out.putShort(index).putByteArray(pool.data, 0, pool.length);

-        out.putShort(access).putShort(name).putShort(superName);

-        out.putShort(interfaceCount);

-        for (int i = 0; i < interfaceCount; ++i) {

-            out.putShort(interfaces[i]);

-        }

-        out.putShort(nbFields);

-        fb = firstField;

-        while (fb != null) {

-            fb.put(out);

-            fb = fb.next;

-        }

-        out.putShort(nbMethods);

-        mb = firstMethod;

-        while (mb != null) {

-            mb.put(out);

-            mb = mb.next;

-        }

-        out.putShort(attributeCount);

-        if (ClassReader.SIGNATURES && signature != 0) {

-            out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);

-        }

-        if (sourceFile != 0) {

-            out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);

-        }

-        if (sourceDebug != null) {

-            int len = sourceDebug.length - 2;

-            out.putShort(newUTF8("SourceDebugExtension")).putInt(len);

-            out.putByteArray(sourceDebug.data, 2, len);

-        }

-        if (enclosingMethodOwner != 0) {

-            out.putShort(newUTF8("EnclosingMethod")).putInt(4);

-            out.putShort(enclosingMethodOwner).putShort(enclosingMethod);

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            out.putShort(newUTF8("Deprecated")).putInt(0);

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (version & 0xffff) < Opcodes.V1_5)

-        {

-            out.putShort(newUTF8("Synthetic")).putInt(0);

-        }

-        if (innerClasses != null) {

-            out.putShort(newUTF8("InnerClasses"));

-            out.putInt(innerClasses.length + 2).putShort(innerClassesCount);

-            out.putByteArray(innerClasses.data, 0, innerClasses.length);

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            out.putShort(newUTF8("RuntimeVisibleAnnotations"));

-            anns.put(out);

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            out.putShort(newUTF8("RuntimeInvisibleAnnotations"));

-            ianns.put(out);

-        }

-        if (attrs != null) {

-            attrs.put(this, null, 0, -1, -1, out);

-        }

-        if (invalidFrames) {

-            ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);

-            new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);

-            return cw.toByteArray();

-        }

-        return out.data;

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods: constant pool management

-    // ------------------------------------------------------------------------

-

-    /**

-     * Adds a number or string constant to the constant pool of the class being

-     * build. Does nothing if the constant pool already contains a similar item.

-     *

-     * @param cst the value of the constant to be added to the constant pool.

-     *        This parameter must be an {@link Integer}, a {@link Float}, a

-     *        {@link Long}, a {@link Double}, a {@link String} or a

-     *        {@link Type}.

-     * @return a new or already existing constant item with the given value.

-     */

-    Item newConstItem(final Object cst) {

-        if (cst instanceof Integer) {

-            int val = ((Integer) cst).intValue();

-            return newInteger(val);

-        } else if (cst instanceof Byte) {

-            int val = ((Byte) cst).intValue();

-            return newInteger(val);

-        } else if (cst instanceof Character) {

-            int val = ((Character) cst).charValue();

-            return newInteger(val);

-        } else if (cst instanceof Short) {

-            int val = ((Short) cst).intValue();

-            return newInteger(val);

-        } else if (cst instanceof Boolean) {

-            int val = ((Boolean) cst).booleanValue() ? 1 : 0;

-            return newInteger(val);

-        } else if (cst instanceof Float) {

-            float val = ((Float) cst).floatValue();

-            return newFloat(val);

-        } else if (cst instanceof Long) {

-            long val = ((Long) cst).longValue();

-            return newLong(val);

-        } else if (cst instanceof Double) {

-            double val = ((Double) cst).doubleValue();

-            return newDouble(val);

-        } else if (cst instanceof String) {

-            return newString((String) cst);

-        } else if (cst instanceof Type) {

-            Type t = (Type) cst;

-            return newClassItem(t.getSort() == Type.OBJECT

-                    ? t.getInternalName()

-                    : t.getDescriptor());

-        } else {

-            throw new IllegalArgumentException("value " + cst);

-        }

-    }

-

-    /**

-     * Adds a number or string constant to the constant pool of the class being

-     * build. Does nothing if the constant pool already contains a similar item.

-     * <i>This method is intended for {@link Attribute} sub classes, and is

-     * normally not needed by class generators or adapters.</i>

-     *

-     * @param cst the value of the constant to be added to the constant pool.

-     *        This parameter must be an {@link Integer}, a {@link Float}, a

-     *        {@link Long}, a {@link Double} or a {@link String}.

-     * @return the index of a new or already existing constant item with the

-     *         given value.

-     */

-    public int newConst(final Object cst) {

-        return newConstItem(cst).index;

-    }

-

-    /**

-     * Adds an UTF8 string to the constant pool of the class being build. Does

-     * nothing if the constant pool already contains a similar item. <i>This

-     * method is intended for {@link Attribute} sub classes, and is normally not

-     * needed by class generators or adapters.</i>

-     *

-     * @param value the String value.

-     * @return the index of a new or already existing UTF8 item.

-     */

-    public int newUTF8(final String value) {

-        key.set(UTF8, value, null, null);

-        Item result = get(key);

-        if (result == null) {

-            pool.putByte(UTF8).putUTF8(value);

-            result = new Item(index++, key);

-            put(result);

-        }

-        return result.index;

-    }

-

-    /**

-     * Adds a class reference to the constant pool of the class being build.

-     * Does nothing if the constant pool already contains a similar item.

-     * <i>This method is intended for {@link Attribute} sub classes, and is

-     * normally not needed by class generators or adapters.</i>

-     *

-     * @param value the internal name of the class.

-     * @return a new or already existing class reference item.

-     */

-    Item newClassItem(final String value) {

-        key2.set(CLASS, value, null, null);

-        Item result = get(key2);

-        if (result == null) {

-            pool.put12(CLASS, newUTF8(value));

-            result = new Item(index++, key2);

-            put(result);

-        }

-        return result;

-    }

-

-    /**

-     * Adds a class reference to the constant pool of the class being build.

-     * Does nothing if the constant pool already contains a similar item.

-     * <i>This method is intended for {@link Attribute} sub classes, and is

-     * normally not needed by class generators or adapters.</i>

-     *

-     * @param value the internal name of the class.

-     * @return the index of a new or already existing class reference item.

-     */

-    public int newClass(final String value) {

-        return newClassItem(value).index;

-    }

-

-    /**

-     * Adds a field reference to the constant pool of the class being build.

-     * Does nothing if the constant pool already contains a similar item.

-     *

-     * @param owner the internal name of the field's owner class.

-     * @param name the field's name.

-     * @param desc the field's descriptor.

-     * @return a new or already existing field reference item.

-     */

-    Item newFieldItem(final String owner, final String name, final String desc)

-    {

-        key3.set(FIELD, owner, name, desc);

-        Item result = get(key3);

-        if (result == null) {

-            put122(FIELD, newClass(owner), newNameType(name, desc));

-            result = new Item(index++, key3);

-            put(result);

-        }

-        return result;

-    }

-

-    /**

-     * Adds a field reference to the constant pool of the class being build.

-     * Does nothing if the constant pool already contains a similar item.

-     * <i>This method is intended for {@link Attribute} sub classes, and is

-     * normally not needed by class generators or adapters.</i>

-     *

-     * @param owner the internal name of the field's owner class.

-     * @param name the field's name.

-     * @param desc the field's descriptor.

-     * @return the index of a new or already existing field reference item.

-     */

-    public int newField(final String owner, final String name, final String desc)

-    {

-        return newFieldItem(owner, name, desc).index;

-    }

-

-    /**

-     * Adds a method reference to the constant pool of the class being build.

-     * Does nothing if the constant pool already contains a similar item.

-     *

-     * @param owner the internal name of the method's owner class.

-     * @param name the method's name.

-     * @param desc the method's descriptor.

-     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.

-     * @return a new or already existing method reference item.

-     */

-    Item newMethodItem(

-        final String owner,

-        final String name,

-        final String desc,

-        final boolean itf)

-    {

-        int type = itf ? IMETH : METH;

-        key3.set(type, owner, name, desc);

-        Item result = get(key3);

-        if (result == null) {

-            put122(type, newClass(owner), newNameType(name, desc));

-            result = new Item(index++, key3);

-            put(result);

-        }

-        return result;

-    }

-

-    /**

-     * Adds a method reference to the constant pool of the class being build.

-     * Does nothing if the constant pool already contains a similar item.

-     * <i>This method is intended for {@link Attribute} sub classes, and is

-     * normally not needed by class generators or adapters.</i>

-     *

-     * @param owner the internal name of the method's owner class.

-     * @param name the method's name.

-     * @param desc the method's descriptor.

-     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.

-     * @return the index of a new or already existing method reference item.

-     */

-    public int newMethod(

-        final String owner,

-        final String name,

-        final String desc,

-        final boolean itf)

-    {

-        return newMethodItem(owner, name, desc, itf).index;

-    }

-

-    /**

-     * Adds an integer to the constant pool of the class being build. Does

-     * nothing if the constant pool already contains a similar item.

-     *

-     * @param value the int value.

-     * @return a new or already existing int item.

-     */

-    Item newInteger(final int value) {

-        key.set(value);

-        Item result = get(key);

-        if (result == null) {

-            pool.putByte(INT).putInt(value);

-            result = new Item(index++, key);

-            put(result);

-        }

-        return result;

-    }

-

-    /**

-     * Adds a float to the constant pool of the class being build. Does nothing

-     * if the constant pool already contains a similar item.

-     *

-     * @param value the float value.

-     * @return a new or already existing float item.

-     */

-    Item newFloat(final float value) {

-        key.set(value);

-        Item result = get(key);

-        if (result == null) {

-            pool.putByte(FLOAT).putInt(key.intVal);

-            result = new Item(index++, key);

-            put(result);

-        }

-        return result;

-    }

-

-    /**

-     * Adds a long to the constant pool of the class being build. Does nothing

-     * if the constant pool already contains a similar item.

-     *

-     * @param value the long value.

-     * @return a new or already existing long item.

-     */

-    Item newLong(final long value) {

-        key.set(value);

-        Item result = get(key);

-        if (result == null) {

-            pool.putByte(LONG).putLong(value);

-            result = new Item(index, key);

-            put(result);

-            index += 2;

-        }

-        return result;

-    }

-

-    /**

-     * Adds a double to the constant pool of the class being build. Does nothing

-     * if the constant pool already contains a similar item.

-     *

-     * @param value the double value.

-     * @return a new or already existing double item.

-     */

-    Item newDouble(final double value) {

-        key.set(value);

-        Item result = get(key);

-        if (result == null) {

-            pool.putByte(DOUBLE).putLong(key.longVal);

-            result = new Item(index, key);

-            put(result);

-            index += 2;

-        }

-        return result;

-    }

-

-    /**

-     * Adds a string to the constant pool of the class being build. Does nothing

-     * if the constant pool already contains a similar item.

-     *

-     * @param value the String value.

-     * @return a new or already existing string item.

-     */

-    private Item newString(final String value) {

-        key2.set(STR, value, null, null);

-        Item result = get(key2);

-        if (result == null) {

-            pool.put12(STR, newUTF8(value));

-            result = new Item(index++, key2);

-            put(result);

-        }

-        return result;

-    }

-

-    /**

-     * Adds a name and type to the constant pool of the class being build. Does

-     * nothing if the constant pool already contains a similar item. <i>This

-     * method is intended for {@link Attribute} sub classes, and is normally not

-     * needed by class generators or adapters.</i>

-     *

-     * @param name a name.

-     * @param desc a type descriptor.

-     * @return the index of a new or already existing name and type item.

-     */

-    public int newNameType(final String name, final String desc) {

-        key2.set(NAME_TYPE, name, desc, null);

-        Item result = get(key2);

-        if (result == null) {

-            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));

-            result = new Item(index++, key2);

-            put(result);

-        }

-        return result.index;

-    }

-

-    /**

-     * Adds the given internal name to {@link #typeTable} and returns its index.

-     * Does nothing if the type table already contains this internal name.

-     *

-     * @param type the internal name to be added to the type table.

-     * @return the index of this internal name in the type table.

-     */

-    int addType(final String type) {

-        key.set(TYPE_NORMAL, type, null, null);

-        Item result = get(key);

-        if (result == null) {

-            result = addType(key);

-        }

-        return result.index;

-    }

-

-    /**

-     * Adds the given "uninitialized" type to {@link #typeTable} and returns its

-     * index. This method is used for UNINITIALIZED types, made of an internal

-     * name and a bytecode offset.

-     *

-     * @param type the internal name to be added to the type table.

-     * @param offset the bytecode offset of the NEW instruction that created

-     *        this UNINITIALIZED type value.

-     * @return the index of this internal name in the type table.

-     */

-    int addUninitializedType(final String type, final int offset) {

-        key.type = TYPE_UNINIT;

-        key.intVal = offset;

-        key.strVal1 = type;

-        key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);

-        Item result = get(key);

-        if (result == null) {

-            result = addType(key);

-        }

-        return result.index;

-    }

-

-    /**

-     * Adds the given Item to {@link #typeTable}.

-     *

-     * @param item the value to be added to the type table.

-     * @return the added Item, which a new Item instance with the same value as

-     *         the given Item.

-     */

-    private Item addType(final Item item) {

-        ++typeCount;

-        Item result = new Item(typeCount, key);

-        put(result);

-        if (typeTable == null) {

-            typeTable = new Item[16];

-        }

-        if (typeCount == typeTable.length) {

-            Item[] newTable = new Item[2 * typeTable.length];

-            System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);

-            typeTable = newTable;

-        }

-        typeTable[typeCount] = result;

-        return result;

-    }

-

-    /**

-     * Returns the index of the common super type of the two given types. This

-     * method calls {@link #getCommonSuperClass} and caches the result in the

-     * {@link #items} hash table to speedup future calls with the same

-     * parameters.

-     *

-     * @param type1 index of an internal name in {@link #typeTable}.

-     * @param type2 index of an internal name in {@link #typeTable}.

-     * @return the index of the common super type of the two given types.

-     */

-    int getMergedType(final int type1, final int type2) {

-        key2.type = TYPE_MERGED;

-        key2.longVal = type1 | (((long) type2) << 32);

-        key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);

-        Item result = get(key2);

-        if (result == null) {

-            String t = typeTable[type1].strVal1;

-            String u = typeTable[type2].strVal1;

-            key2.intVal = addType(getCommonSuperClass(t, u));

-            result = new Item((short) 0, key2);

-            put(result);

-        }

-        return result.intVal;

-    }

-

-    /**

-     * Returns the common super type of the two given types. The default

-     * implementation of this method <i>loads<i> the two given classes and uses

-     * the java.lang.Class methods to find the common super class. It can be

-     * overridden to compute this common super type in other ways, in particular

-     * without actually loading any class, or to take into account the class

-     * that is currently being generated by this ClassWriter, which can of

-     * course not be loaded since it is under construction.

-     *

-     * @param type1 the internal name of a class.

-     * @param type2 the internal name of another class.

-     * @return the internal name of the common super class of the two given

-     *         classes.

-     */

-    protected String getCommonSuperClass(final String type1, final String type2)

-    {

-        Class c, d;

-        try {

-            c = Class.forName(type1.replace('/', '.'));

-            d = Class.forName(type2.replace('/', '.'));

-        } catch (Exception e) {

-            throw new RuntimeException(e.toString());

-        }

-        if (c.isAssignableFrom(d)) {

-            return type1;

-        }

-        if (d.isAssignableFrom(c)) {

-            return type2;

-        }

-        if (c.isInterface() || d.isInterface()) {

-            return "java/lang/Object";

-        } else {

-            do {

-                c = c.getSuperclass();

-            } while (!c.isAssignableFrom(d));

-            return c.getName().replace('.', '/');

-        }

-    }

-

-    /**

-     * Returns the constant pool's hash table item which is equal to the given

-     * item.

-     *

-     * @param key a constant pool item.

-     * @return the constant pool's hash table item which is equal to the given

-     *         item, or <tt>null</tt> if there is no such item.

-     */

-    private Item get(final Item key) {

-        Item i = items[key.hashCode % items.length];

-        while (i != null && !key.isEqualTo(i)) {

-            i = i.next;

-        }

-        return i;

-    }

-

-    /**

-     * Puts the given item in the constant pool's hash table. The hash table

-     * <i>must</i> not already contains this item.

-     *

-     * @param i the item to be added to the constant pool's hash table.

-     */

-    private void put(final Item i) {

-        if (index > threshold) {

-            int ll = items.length;

-            int nl = ll * 2 + 1;

-            Item[] newItems = new Item[nl];

-            for (int l = ll - 1; l >= 0; --l) {

-                Item j = items[l];

-                while (j != null) {

-                    int index = j.hashCode % newItems.length;

-                    Item k = j.next;

-                    j.next = newItems[index];

-                    newItems[index] = j;

-                    j = k;

-                }

-            }

-            items = newItems;

-            threshold = (int) (nl * 0.75);

-        }

-        int index = i.hashCode % items.length;

-        i.next = items[index];

-        items[index] = i;

-    }

-

-    /**

-     * Puts one byte and two shorts into the constant pool.

-     *

-     * @param b a byte.

-     * @param s1 a short.

-     * @param s2 another short.

-     */

-    private void put122(final int b, final int s1, final int s2) {

-        pool.put12(b, s1).putShort(s2);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Edge.java b/cglib-and-asm/src/org/mockito/asm/Edge.java
deleted file mode 100644
index 587f334..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Edge.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * An edge in the control flow graph of a method body. See {@link Label Label}.

- * 

- * @author Eric Bruneton

- */

-class Edge {

-

-    /**

-     * Denotes a normal control flow graph edge.

-     */

-    static final int NORMAL = 0;

-

-    /**

-     * Denotes a control flow graph edge corresponding to an exception handler.

-     * More precisely any {@link Edge} whose {@link #info} is strictly positive

-     * corresponds to an exception handler. The actual value of {@link #info} is

-     * the index, in the {@link ClassWriter} type table, of the exception that

-     * is catched.

-     */

-    static final int EXCEPTION = 0x7FFFFFFF;

-

-    /**

-     * Information about this control flow graph edge. If

-     * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)

-     * stack size in the basic block from which this edge originates. This size

-     * is equal to the stack size at the "jump" instruction to which this edge

-     * corresponds, relatively to the stack size at the beginning of the

-     * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,

-     * this field is the kind of this control flow graph edge (i.e. NORMAL or

-     * EXCEPTION).

-     */

-    int info;

-

-    /**

-     * The successor block of the basic block from which this edge originates.

-     */

-    Label successor;

-

-    /**

-     * The next edge in the list of successors of the originating basic block.

-     * See {@link Label#successors successors}.

-     */

-    Edge next;

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/FieldVisitor.java b/cglib-and-asm/src/org/mockito/asm/FieldVisitor.java
deleted file mode 100644
index 24c18b1..0000000
--- a/cglib-and-asm/src/org/mockito/asm/FieldVisitor.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A visitor to visit a Java field. The methods of this interface must be called

- * in the following order: ( <tt>visitAnnotation</tt> |

- * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.

- * 

- * @author Eric Bruneton

- */

-public interface FieldVisitor {

-

-    /**

-     * Visits an annotation of the field.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values, or <tt>null</tt> if

-     *         this visitor is not interested in visiting this annotation.

-     */

-    AnnotationVisitor visitAnnotation(String desc, boolean visible);

-

-    /**

-     * Visits a non standard attribute of the field.

-     * 

-     * @param attr an attribute.

-     */

-    void visitAttribute(Attribute attr);

-

-    /**

-     * Visits the end of the field. This method, which is the last one to be

-     * called, is used to inform the visitor that all the annotations and

-     * attributes of the field have been visited.

-     */

-    void visitEnd();

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/FieldWriter.java b/cglib-and-asm/src/org/mockito/asm/FieldWriter.java
deleted file mode 100644
index 99db9a3..0000000
--- a/cglib-and-asm/src/org/mockito/asm/FieldWriter.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * An {@link FieldVisitor} that generates Java fields in bytecode form.

- * 

- * @author Eric Bruneton

- */

-final class FieldWriter implements FieldVisitor {

-

-    /**

-     * Next field writer (see {@link ClassWriter#firstField firstField}).

-     */

-    FieldWriter next;

-

-    /**

-     * The class writer to which this field must be added.

-     */

-    private final ClassWriter cw;

-

-    /**

-     * Access flags of this field.

-     */

-    private final int access;

-

-    /**

-     * The index of the constant pool item that contains the name of this

-     * method.

-     */

-    private final int name;

-

-    /**

-     * The index of the constant pool item that contains the descriptor of this

-     * field.

-     */

-    private final int desc;

-

-    /**

-     * The index of the constant pool item that contains the signature of this

-     * field.

-     */

-    private int signature;

-

-    /**

-     * The index of the constant pool item that contains the constant value of

-     * this field.

-     */

-    private int value;

-

-    /**

-     * The runtime visible annotations of this field. May be <tt>null</tt>.

-     */

-    private AnnotationWriter anns;

-

-    /**

-     * The runtime invisible annotations of this field. May be <tt>null</tt>.

-     */

-    private AnnotationWriter ianns;

-

-    /**

-     * The non standard attributes of this field. May be <tt>null</tt>.

-     */

-    private Attribute attrs;

-

-    // ------------------------------------------------------------------------

-    // Constructor

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a new {@link FieldWriter}.

-     * 

-     * @param cw the class writer to which this field must be added.

-     * @param access the field's access flags (see {@link Opcodes}).

-     * @param name the field's name.

-     * @param desc the field's descriptor (see {@link Type}).

-     * @param signature the field's signature. May be <tt>null</tt>.

-     * @param value the field's constant value. May be <tt>null</tt>.

-     */

-    FieldWriter(

-        final ClassWriter cw,

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        if (cw.firstField == null) {

-            cw.firstField = this;

-        } else {

-            cw.lastField.next = this;

-        }

-        cw.lastField = this;

-        this.cw = cw;

-        this.access = access;

-        this.name = cw.newUTF8(name);

-        this.desc = cw.newUTF8(desc);

-        if (ClassReader.SIGNATURES && signature != null) {

-            this.signature = cw.newUTF8(signature);

-        }

-        if (value != null) {

-            this.value = cw.newConstItem(value).index;

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the FieldVisitor interface

-    // ------------------------------------------------------------------------

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        if (!ClassReader.ANNOTATIONS) {

-            return null;

-        }

-        ByteVector bv = new ByteVector();

-        // write type, and reserve space for values count

-        bv.putShort(cw.newUTF8(desc)).putShort(0);

-        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);

-        if (visible) {

-            aw.next = anns;

-            anns = aw;

-        } else {

-            aw.next = ianns;

-            ianns = aw;

-        }

-        return aw;

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        attr.next = attrs;

-        attrs = attr;

-    }

-

-    public void visitEnd() {

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the size of this field.

-     * 

-     * @return the size of this field.

-     */

-    int getSize() {

-        int size = 8;

-        if (value != 0) {

-            cw.newUTF8("ConstantValue");

-            size += 8;

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (cw.version & 0xffff) < Opcodes.V1_5)

-        {

-            cw.newUTF8("Synthetic");

-            size += 6;

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            cw.newUTF8("Deprecated");

-            size += 6;

-        }

-        if (ClassReader.SIGNATURES && signature != 0) {

-            cw.newUTF8("Signature");

-            size += 8;

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            cw.newUTF8("RuntimeVisibleAnnotations");

-            size += 8 + anns.getSize();

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            cw.newUTF8("RuntimeInvisibleAnnotations");

-            size += 8 + ianns.getSize();

-        }

-        if (attrs != null) {

-            size += attrs.getSize(cw, null, 0, -1, -1);

-        }

-        return size;

-    }

-

-    /**

-     * Puts the content of this field into the given byte vector.

-     * 

-     * @param out where the content of this field must be put.

-     */

-    void put(final ByteVector out) {

-        out.putShort(access).putShort(name).putShort(desc);

-        int attributeCount = 0;

-        if (value != 0) {

-            ++attributeCount;

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (cw.version & 0xffff) < Opcodes.V1_5)

-        {

-            ++attributeCount;

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            ++attributeCount;

-        }

-        if (ClassReader.SIGNATURES && signature != 0) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            ++attributeCount;

-        }

-        if (attrs != null) {

-            attributeCount += attrs.getCount();

-        }

-        out.putShort(attributeCount);

-        if (value != 0) {

-            out.putShort(cw.newUTF8("ConstantValue"));

-            out.putInt(2).putShort(value);

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (cw.version & 0xffff) < Opcodes.V1_5)

-        {

-            out.putShort(cw.newUTF8("Synthetic")).putInt(0);

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            out.putShort(cw.newUTF8("Deprecated")).putInt(0);

-        }

-        if (ClassReader.SIGNATURES && signature != 0) {

-            out.putShort(cw.newUTF8("Signature"));

-            out.putInt(2).putShort(signature);

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));

-            anns.put(out);

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));

-            ianns.put(out);

-        }

-        if (attrs != null) {

-            attrs.put(cw, null, 0, -1, -1, out);

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Frame.java b/cglib-and-asm/src/org/mockito/asm/Frame.java
deleted file mode 100644
index d1a4532..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Frame.java
+++ /dev/null
@@ -1,1402 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * Information about the input and output stack map frames of a basic block.

- * 

- * @author Eric Bruneton

- */

-final class Frame {

-

-    /*

-     * Frames are computed in a two steps process: during the visit of each

-     * instruction, the state of the frame at the end of current basic block is

-     * updated by simulating the action of the instruction on the previous state

-     * of this so called "output frame". In visitMaxs, a fix point algorithm is

-     * used to compute the "input frame" of each basic block, i.e. the stack map

-     * frame at the begining of the basic block, starting from the input frame

-     * of the first basic block (which is computed from the method descriptor),

-     * and by using the previously computed output frames to compute the input

-     * state of the other blocks.

-     * 

-     * All output and input frames are stored as arrays of integers. Reference

-     * and array types are represented by an index into a type table (which is

-     * not the same as the constant pool of the class, in order to avoid adding

-     * unnecessary constants in the pool - not all computed frames will end up

-     * being stored in the stack map table). This allows very fast type

-     * comparisons.

-     * 

-     * Output stack map frames are computed relatively to the input frame of the

-     * basic block, which is not yet known when output frames are computed. It

-     * is therefore necessary to be able to represent abstract types such as

-     * "the type at position x in the input frame locals" or "the type at

-     * position x from the top of the input frame stack" or even "the type at

-     * position x in the input frame, with y more (or less) array dimensions".

-     * This explains the rather complicated type format used in output frames.

-     * 

-     * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a

-     * signed number of array dimensions (from -8 to 7). KIND is either BASE,

-     * LOCAL or STACK. BASE is used for types that are not relative to the input

-     * frame. LOCAL is used for types that are relative to the input local

-     * variable types. STACK is used for types that are relative to the input

-     * stack types. VALUE depends on KIND. For LOCAL types, it is an index in

-     * the input local variable types. For STACK types, it is a position

-     * relatively to the top of input frame stack. For BASE types, it is either

-     * one of the constants defined in FrameVisitor, or for OBJECT and

-     * UNINITIALIZED types, a tag and an index in the type table.

-     * 

-     * Output frames can contain types of any kind and with a positive or

-     * negative dimension (and even unassigned types, represented by 0 - which

-     * does not correspond to any valid type value). Input frames can only

-     * contain BASE types of positive or null dimension. In all cases the type

-     * table contains only internal type names (array type descriptors are

-     * forbidden - dimensions must be represented through the DIM field).

-     * 

-     * The LONG and DOUBLE types are always represented by using two slots (LONG +

-     * TOP or DOUBLE + TOP), for local variable types as well as in the operand

-     * stack. This is necessary to be able to simulate DUPx_y instructions,

-     * whose effect would be dependent on the actual type values if types were

-     * always represented by a single slot in the stack (and this is not

-     * possible, since actual type values are not always known - cf LOCAL and

-     * STACK type kinds).

-     */

-

-    /**

-     * Mask to get the dimension of a frame type. This dimension is a signed

-     * integer between -8 and 7.

-     */

-    static final int DIM = 0xF0000000;

-

-    /**

-     * Constant to be added to a type to get a type with one more dimension.

-     */

-    static final int ARRAY_OF = 0x10000000;

-

-    /**

-     * Constant to be added to a type to get a type with one less dimension.

-     */

-    static final int ELEMENT_OF = 0xF0000000;

-

-    /**

-     * Mask to get the kind of a frame type.

-     * 

-     * @see #BASE

-     * @see #LOCAL

-     * @see #STACK

-     */

-    static final int KIND = 0xF000000;

-

-    /**

-     * Mask to get the value of a frame type.

-     */

-    static final int VALUE = 0xFFFFFF;

-

-    /**

-     * Mask to get the kind of base types.

-     */

-    static final int BASE_KIND = 0xFF00000;

-

-    /**

-     * Mask to get the value of base types.

-     */

-    static final int BASE_VALUE = 0xFFFFF;

-

-    /**

-     * Kind of the types that are not relative to an input stack map frame.

-     */

-    static final int BASE = 0x1000000;

-

-    /**

-     * Base kind of the base reference types. The BASE_VALUE of such types is an

-     * index into the type table.

-     */

-    static final int OBJECT = BASE | 0x700000;

-

-    /**

-     * Base kind of the uninitialized base types. The BASE_VALUE of such types

-     * in an index into the type table (the Item at that index contains both an

-     * instruction offset and an internal class name).

-     */

-    static final int UNINITIALIZED = BASE | 0x800000;

-

-    /**

-     * Kind of the types that are relative to the local variable types of an

-     * input stack map frame. The value of such types is a local variable index.

-     */

-    private static final int LOCAL = 0x2000000;

-

-    /**

-     * Kind of the the types that are relative to the stack of an input stack

-     * map frame. The value of such types is a position relatively to the top of

-     * this stack.

-     */

-    private static final int STACK = 0x3000000;

-

-    /**

-     * The TOP type. This is a BASE type.

-     */

-    static final int TOP = BASE | 0;

-

-    /**

-     * The BOOLEAN type. This is a BASE type mainly used for array types.

-     */

-    static final int BOOLEAN = BASE | 9;

-

-    /**

-     * The BYTE type. This is a BASE type mainly used for array types.

-     */

-    static final int BYTE = BASE | 10;

-

-    /**

-     * The CHAR type. This is a BASE type mainly used for array types.

-     */

-    static final int CHAR = BASE | 11;

-

-    /**

-     * The SHORT type. This is a BASE type mainly used for array types.

-     */

-    static final int SHORT = BASE | 12;

-

-    /**

-     * The INTEGER type. This is a BASE type.

-     */

-    static final int INTEGER = BASE | 1;

-

-    /**

-     * The FLOAT type. This is a BASE type.

-     */

-    static final int FLOAT = BASE | 2;

-

-    /**

-     * The DOUBLE type. This is a BASE type.

-     */

-    static final int DOUBLE = BASE | 3;

-

-    /**

-     * The LONG type. This is a BASE type.

-     */

-    static final int LONG = BASE | 4;

-

-    /**

-     * The NULL type. This is a BASE type.

-     */

-    static final int NULL = BASE | 5;

-

-    /**

-     * The UNINITIALIZED_THIS type. This is a BASE type.

-     */

-    static final int UNINITIALIZED_THIS = BASE | 6;

-

-    /**

-     * The stack size variation corresponding to each JVM instruction. This

-     * stack variation is equal to the size of the values produced by an

-     * instruction, minus the size of the values consumed by this instruction.

-     */

-    static final int[] SIZE;

-

-    /**

-     * Computes the stack size variation corresponding to each JVM instruction.

-     */

-    static {

-        int i;

-        int[] b = new int[202];

-        String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"

-                + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"

-                + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"

-                + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";

-        for (i = 0; i < b.length; ++i) {

-            b[i] = s.charAt(i) - 'E';

-        }

-        SIZE = b;

-

-        // code to generate the above string

-        //

-        // int NA = 0; // not applicable (unused opcode or variable size opcode)

-        //

-        // b = new int[] {

-        // 0, //NOP, // visitInsn

-        // 1, //ACONST_NULL, // -

-        // 1, //ICONST_M1, // -

-        // 1, //ICONST_0, // -

-        // 1, //ICONST_1, // -

-        // 1, //ICONST_2, // -

-        // 1, //ICONST_3, // -

-        // 1, //ICONST_4, // -

-        // 1, //ICONST_5, // -

-        // 2, //LCONST_0, // -

-        // 2, //LCONST_1, // -

-        // 1, //FCONST_0, // -

-        // 1, //FCONST_1, // -

-        // 1, //FCONST_2, // -

-        // 2, //DCONST_0, // -

-        // 2, //DCONST_1, // -

-        // 1, //BIPUSH, // visitIntInsn

-        // 1, //SIPUSH, // -

-        // 1, //LDC, // visitLdcInsn

-        // NA, //LDC_W, // -

-        // NA, //LDC2_W, // -

-        // 1, //ILOAD, // visitVarInsn

-        // 2, //LLOAD, // -

-        // 1, //FLOAD, // -

-        // 2, //DLOAD, // -

-        // 1, //ALOAD, // -

-        // NA, //ILOAD_0, // -

-        // NA, //ILOAD_1, // -

-        // NA, //ILOAD_2, // -

-        // NA, //ILOAD_3, // -

-        // NA, //LLOAD_0, // -

-        // NA, //LLOAD_1, // -

-        // NA, //LLOAD_2, // -

-        // NA, //LLOAD_3, // -

-        // NA, //FLOAD_0, // -

-        // NA, //FLOAD_1, // -

-        // NA, //FLOAD_2, // -

-        // NA, //FLOAD_3, // -

-        // NA, //DLOAD_0, // -

-        // NA, //DLOAD_1, // -

-        // NA, //DLOAD_2, // -

-        // NA, //DLOAD_3, // -

-        // NA, //ALOAD_0, // -

-        // NA, //ALOAD_1, // -

-        // NA, //ALOAD_2, // -

-        // NA, //ALOAD_3, // -

-        // -1, //IALOAD, // visitInsn

-        // 0, //LALOAD, // -

-        // -1, //FALOAD, // -

-        // 0, //DALOAD, // -

-        // -1, //AALOAD, // -

-        // -1, //BALOAD, // -

-        // -1, //CALOAD, // -

-        // -1, //SALOAD, // -

-        // -1, //ISTORE, // visitVarInsn

-        // -2, //LSTORE, // -

-        // -1, //FSTORE, // -

-        // -2, //DSTORE, // -

-        // -1, //ASTORE, // -

-        // NA, //ISTORE_0, // -

-        // NA, //ISTORE_1, // -

-        // NA, //ISTORE_2, // -

-        // NA, //ISTORE_3, // -

-        // NA, //LSTORE_0, // -

-        // NA, //LSTORE_1, // -

-        // NA, //LSTORE_2, // -

-        // NA, //LSTORE_3, // -

-        // NA, //FSTORE_0, // -

-        // NA, //FSTORE_1, // -

-        // NA, //FSTORE_2, // -

-        // NA, //FSTORE_3, // -

-        // NA, //DSTORE_0, // -

-        // NA, //DSTORE_1, // -

-        // NA, //DSTORE_2, // -

-        // NA, //DSTORE_3, // -

-        // NA, //ASTORE_0, // -

-        // NA, //ASTORE_1, // -

-        // NA, //ASTORE_2, // -

-        // NA, //ASTORE_3, // -

-        // -3, //IASTORE, // visitInsn

-        // -4, //LASTORE, // -

-        // -3, //FASTORE, // -

-        // -4, //DASTORE, // -

-        // -3, //AASTORE, // -

-        // -3, //BASTORE, // -

-        // -3, //CASTORE, // -

-        // -3, //SASTORE, // -

-        // -1, //POP, // -

-        // -2, //POP2, // -

-        // 1, //DUP, // -

-        // 1, //DUP_X1, // -

-        // 1, //DUP_X2, // -

-        // 2, //DUP2, // -

-        // 2, //DUP2_X1, // -

-        // 2, //DUP2_X2, // -

-        // 0, //SWAP, // -

-        // -1, //IADD, // -

-        // -2, //LADD, // -

-        // -1, //FADD, // -

-        // -2, //DADD, // -

-        // -1, //ISUB, // -

-        // -2, //LSUB, // -

-        // -1, //FSUB, // -

-        // -2, //DSUB, // -

-        // -1, //IMUL, // -

-        // -2, //LMUL, // -

-        // -1, //FMUL, // -

-        // -2, //DMUL, // -

-        // -1, //IDIV, // -

-        // -2, //LDIV, // -

-        // -1, //FDIV, // -

-        // -2, //DDIV, // -

-        // -1, //IREM, // -

-        // -2, //LREM, // -

-        // -1, //FREM, // -

-        // -2, //DREM, // -

-        // 0, //INEG, // -

-        // 0, //LNEG, // -

-        // 0, //FNEG, // -

-        // 0, //DNEG, // -

-        // -1, //ISHL, // -

-        // -1, //LSHL, // -

-        // -1, //ISHR, // -

-        // -1, //LSHR, // -

-        // -1, //IUSHR, // -

-        // -1, //LUSHR, // -

-        // -1, //IAND, // -

-        // -2, //LAND, // -

-        // -1, //IOR, // -

-        // -2, //LOR, // -

-        // -1, //IXOR, // -

-        // -2, //LXOR, // -

-        // 0, //IINC, // visitIincInsn

-        // 1, //I2L, // visitInsn

-        // 0, //I2F, // -

-        // 1, //I2D, // -

-        // -1, //L2I, // -

-        // -1, //L2F, // -

-        // 0, //L2D, // -

-        // 0, //F2I, // -

-        // 1, //F2L, // -

-        // 1, //F2D, // -

-        // -1, //D2I, // -

-        // 0, //D2L, // -

-        // -1, //D2F, // -

-        // 0, //I2B, // -

-        // 0, //I2C, // -

-        // 0, //I2S, // -

-        // -3, //LCMP, // -

-        // -1, //FCMPL, // -

-        // -1, //FCMPG, // -

-        // -3, //DCMPL, // -

-        // -3, //DCMPG, // -

-        // -1, //IFEQ, // visitJumpInsn

-        // -1, //IFNE, // -

-        // -1, //IFLT, // -

-        // -1, //IFGE, // -

-        // -1, //IFGT, // -

-        // -1, //IFLE, // -

-        // -2, //IF_ICMPEQ, // -

-        // -2, //IF_ICMPNE, // -

-        // -2, //IF_ICMPLT, // -

-        // -2, //IF_ICMPGE, // -

-        // -2, //IF_ICMPGT, // -

-        // -2, //IF_ICMPLE, // -

-        // -2, //IF_ACMPEQ, // -

-        // -2, //IF_ACMPNE, // -

-        // 0, //GOTO, // -

-        // 1, //JSR, // -

-        // 0, //RET, // visitVarInsn

-        // -1, //TABLESWITCH, // visiTableSwitchInsn

-        // -1, //LOOKUPSWITCH, // visitLookupSwitch

-        // -1, //IRETURN, // visitInsn

-        // -2, //LRETURN, // -

-        // -1, //FRETURN, // -

-        // -2, //DRETURN, // -

-        // -1, //ARETURN, // -

-        // 0, //RETURN, // -

-        // NA, //GETSTATIC, // visitFieldInsn

-        // NA, //PUTSTATIC, // -

-        // NA, //GETFIELD, // -

-        // NA, //PUTFIELD, // -

-        // NA, //INVOKEVIRTUAL, // visitMethodInsn

-        // NA, //INVOKESPECIAL, // -

-        // NA, //INVOKESTATIC, // -

-        // NA, //INVOKEINTERFACE, // -

-        // NA, //UNUSED, // NOT VISITED

-        // 1, //NEW, // visitTypeInsn

-        // 0, //NEWARRAY, // visitIntInsn

-        // 0, //ANEWARRAY, // visitTypeInsn

-        // 0, //ARRAYLENGTH, // visitInsn

-        // NA, //ATHROW, // -

-        // 0, //CHECKCAST, // visitTypeInsn

-        // 0, //INSTANCEOF, // -

-        // -1, //MONITORENTER, // visitInsn

-        // -1, //MONITOREXIT, // -

-        // NA, //WIDE, // NOT VISITED

-        // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn

-        // -1, //IFNULL, // visitJumpInsn

-        // -1, //IFNONNULL, // -

-        // NA, //GOTO_W, // -

-        // NA, //JSR_W, // -

-        // };

-        // for (i = 0; i < b.length; ++i) {

-        // System.err.print((char)('E' + b[i]));

-        // }

-        // System.err.println();

-    }

-

-    /**

-     * The label (i.e. basic block) to which these input and output stack map

-     * frames correspond.

-     */

-    Label owner;

-

-    /**

-     * The input stack map frame locals.

-     */

-    int[] inputLocals;

-

-    /**

-     * The input stack map frame stack.

-     */

-    int[] inputStack;

-

-    /**

-     * The output stack map frame locals.

-     */

-    private int[] outputLocals;

-

-    /**

-     * The output stack map frame stack.

-     */

-    private int[] outputStack;

-

-    /**

-     * Relative size of the output stack. The exact semantics of this field

-     * depends on the algorithm that is used.

-     * 

-     * When only the maximum stack size is computed, this field is the size of

-     * the output stack relatively to the top of the input stack.

-     * 

-     * When the stack map frames are completely computed, this field is the

-     * actual number of types in {@link #outputStack}.

-     */

-    private int outputStackTop;

-

-    /**

-     * Number of types that are initialized in the basic block.

-     * 

-     * @see #initializations

-     */

-    private int initializationCount;

-

-    /**

-     * The types that are initialized in the basic block. A constructor

-     * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace

-     * <i>every occurence</i> of this type in the local variables and in the

-     * operand stack. This cannot be done during the first phase of the

-     * algorithm since, during this phase, the local variables and the operand

-     * stack are not completely computed. It is therefore necessary to store the

-     * types on which constructors are invoked in the basic block, in order to

-     * do this replacement during the second phase of the algorithm, where the

-     * frames are fully computed. Note that this array can contain types that

-     * are relative to input locals or to the input stack (see below for the

-     * description of the algorithm).

-     */

-    private int[] initializations;

-

-    /**

-     * Returns the output frame local variable type at the given index.

-     * 

-     * @param local the index of the local that must be returned.

-     * @return the output frame local variable type at the given index.

-     */

-    private int get(final int local) {

-        if (outputLocals == null || local >= outputLocals.length) {

-            // this local has never been assigned in this basic block,

-            // so it is still equal to its value in the input frame

-            return LOCAL | local;

-        } else {

-            int type = outputLocals[local];

-            if (type == 0) {

-                // this local has never been assigned in this basic block,

-                // so it is still equal to its value in the input frame

-                type = outputLocals[local] = LOCAL | local;

-            }

-            return type;

-        }

-    }

-

-    /**

-     * Sets the output frame local variable type at the given index.

-     * 

-     * @param local the index of the local that must be set.

-     * @param type the value of the local that must be set.

-     */

-    private void set(final int local, final int type) {

-        // creates and/or resizes the output local variables array if necessary

-        if (outputLocals == null) {

-            outputLocals = new int[10];

-        }

-        int n = outputLocals.length;

-        if (local >= n) {

-            int[] t = new int[Math.max(local + 1, 2 * n)];

-            System.arraycopy(outputLocals, 0, t, 0, n);

-            outputLocals = t;

-        }

-        // sets the local variable

-        outputLocals[local] = type;

-    }

-

-    /**

-     * Pushes a new type onto the output frame stack.

-     * 

-     * @param type the type that must be pushed.

-     */

-    private void push(final int type) {

-        // creates and/or resizes the output stack array if necessary

-        if (outputStack == null) {

-            outputStack = new int[10];

-        }

-        int n = outputStack.length;

-        if (outputStackTop >= n) {

-            int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];

-            System.arraycopy(outputStack, 0, t, 0, n);

-            outputStack = t;

-        }

-        // pushes the type on the output stack

-        outputStack[outputStackTop++] = type;

-        // updates the maximun height reached by the output stack, if needed

-        int top = owner.inputStackTop + outputStackTop;

-        if (top > owner.outputStackMax) {

-            owner.outputStackMax = top;

-        }

-    }

-

-    /**

-     * Pushes a new type onto the output frame stack.

-     * 

-     * @param cw the ClassWriter to which this label belongs.

-     * @param desc the descriptor of the type to be pushed. Can also be a method

-     *        descriptor (in this case this method pushes its return type onto

-     *        the output frame stack).

-     */

-    private void push(final ClassWriter cw, final String desc) {

-        int type = type(cw, desc);

-        if (type != 0) {

-            push(type);

-            if (type == LONG || type == DOUBLE) {

-                push(TOP);

-            }

-        }

-    }

-

-    /**

-     * Returns the int encoding of the given type.

-     * 

-     * @param cw the ClassWriter to which this label belongs.

-     * @param desc a type descriptor.

-     * @return the int encoding of the given type.

-     */

-    private static int type(final ClassWriter cw, final String desc) {

-        String t;

-        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;

-        switch (desc.charAt(index)) {

-            case 'V':

-                return 0;

-            case 'Z':

-            case 'C':

-            case 'B':

-            case 'S':

-            case 'I':

-                return INTEGER;

-            case 'F':

-                return FLOAT;

-            case 'J':

-                return LONG;

-            case 'D':

-                return DOUBLE;

-            case 'L':

-                // stores the internal name, not the descriptor!

-                t = desc.substring(index + 1, desc.length() - 1);

-                return OBJECT | cw.addType(t);

-                // case '[':

-            default:

-                // extracts the dimensions and the element type

-                int data;

-                int dims = index + 1;

-                while (desc.charAt(dims) == '[') {

-                    ++dims;

-                }

-                switch (desc.charAt(dims)) {

-                    case 'Z':

-                        data = BOOLEAN;

-                        break;

-                    case 'C':

-                        data = CHAR;

-                        break;

-                    case 'B':

-                        data = BYTE;

-                        break;

-                    case 'S':

-                        data = SHORT;

-                        break;

-                    case 'I':

-                        data = INTEGER;

-                        break;

-                    case 'F':

-                        data = FLOAT;

-                        break;

-                    case 'J':

-                        data = LONG;

-                        break;

-                    case 'D':

-                        data = DOUBLE;

-                        break;

-                    // case 'L':

-                    default:

-                        // stores the internal name, not the descriptor

-                        t = desc.substring(dims + 1, desc.length() - 1);

-                        data = OBJECT | cw.addType(t);

-                }

-                return (dims - index) << 28 | data;

-        }

-    }

-

-    /**

-     * Pops a type from the output frame stack and returns its value.

-     * 

-     * @return the type that has been popped from the output frame stack.

-     */

-    private int pop() {

-        if (outputStackTop > 0) {

-            return outputStack[--outputStackTop];

-        } else {

-            // if the output frame stack is empty, pops from the input stack

-            return STACK | -(--owner.inputStackTop);

-        }

-    }

-

-    /**

-     * Pops the given number of types from the output frame stack.

-     * 

-     * @param elements the number of types that must be popped.

-     */

-    private void pop(final int elements) {

-        if (outputStackTop >= elements) {

-            outputStackTop -= elements;

-        } else {

-            // if the number of elements to be popped is greater than the number

-            // of elements in the output stack, clear it, and pops the remaining

-            // elements from the input stack.

-            owner.inputStackTop -= elements - outputStackTop;

-            outputStackTop = 0;

-        }

-    }

-

-    /**

-     * Pops a type from the output frame stack.

-     * 

-     * @param desc the descriptor of the type to be popped. Can also be a method

-     *        descriptor (in this case this method pops the types corresponding

-     *        to the method arguments).

-     */

-    private void pop(final String desc) {

-        char c = desc.charAt(0);

-        if (c == '(') {

-            pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);

-        } else if (c == 'J' || c == 'D') {

-            pop(2);

-        } else {

-            pop(1);

-        }

-    }

-

-    /**

-     * Adds a new type to the list of types on which a constructor is invoked in

-     * the basic block.

-     * 

-     * @param var a type on a which a constructor is invoked.

-     */

-    private void init(final int var) {

-        // creates and/or resizes the initializations array if necessary

-        if (initializations == null) {

-            initializations = new int[2];

-        }

-        int n = initializations.length;

-        if (initializationCount >= n) {

-            int[] t = new int[Math.max(initializationCount + 1, 2 * n)];

-            System.arraycopy(initializations, 0, t, 0, n);

-            initializations = t;

-        }

-        // stores the type to be initialized

-        initializations[initializationCount++] = var;

-    }

-

-    /**

-     * Replaces the given type with the appropriate type if it is one of the

-     * types on which a constructor is invoked in the basic block.

-     * 

-     * @param cw the ClassWriter to which this label belongs.

-     * @param t a type

-     * @return t or, if t is one of the types on which a constructor is invoked

-     *         in the basic block, the type corresponding to this constructor.

-     */

-    private int init(final ClassWriter cw, final int t) {

-        int s;

-        if (t == UNINITIALIZED_THIS) {

-            s = OBJECT | cw.addType(cw.thisName);

-        } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {

-            String type = cw.typeTable[t & BASE_VALUE].strVal1;

-            s = OBJECT | cw.addType(type);

-        } else {

-            return t;

-        }

-        for (int j = 0; j < initializationCount; ++j) {

-            int u = initializations[j];

-            int dim = u & DIM;

-            int kind = u & KIND;

-            if (kind == LOCAL) {

-                u = dim + inputLocals[u & VALUE];

-            } else if (kind == STACK) {

-                u = dim + inputStack[inputStack.length - (u & VALUE)];

-            }

-            if (t == u) {

-                return s;

-            }

-        }

-        return t;

-    }

-

-    /**

-     * Initializes the input frame of the first basic block from the method

-     * descriptor.

-     * 

-     * @param cw the ClassWriter to which this label belongs.

-     * @param access the access flags of the method to which this label belongs.

-     * @param args the formal parameter types of this method.

-     * @param maxLocals the maximum number of local variables of this method.

-     */

-    void initInputFrame(

-        final ClassWriter cw,

-        final int access,

-        final Type[] args,

-        final int maxLocals)

-    {

-        inputLocals = new int[maxLocals];

-        inputStack = new int[0];

-        int i = 0;

-        if ((access & Opcodes.ACC_STATIC) == 0) {

-            if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {

-                inputLocals[i++] = OBJECT | cw.addType(cw.thisName);

-            } else {

-                inputLocals[i++] = UNINITIALIZED_THIS;

-            }

-        }

-        for (int j = 0; j < args.length; ++j) {

-            int t = type(cw, args[j].getDescriptor());

-            inputLocals[i++] = t;

-            if (t == LONG || t == DOUBLE) {

-                inputLocals[i++] = TOP;

-            }

-        }

-        while (i < maxLocals) {

-            inputLocals[i++] = TOP;

-        }

-    }

-

-    /**

-     * Simulates the action of the given instruction on the output stack frame.

-     * 

-     * @param opcode the opcode of the instruction.

-     * @param arg the operand of the instruction, if any.

-     * @param cw the class writer to which this label belongs.

-     * @param item the operand of the instructions, if any.

-     */

-    void execute(

-        final int opcode,

-        final int arg,

-        final ClassWriter cw,

-        final Item item)

-    {

-        int t1, t2, t3, t4;

-        switch (opcode) {

-            case Opcodes.NOP:

-            case Opcodes.INEG:

-            case Opcodes.LNEG:

-            case Opcodes.FNEG:

-            case Opcodes.DNEG:

-            case Opcodes.I2B:

-            case Opcodes.I2C:

-            case Opcodes.I2S:

-            case Opcodes.GOTO:

-            case Opcodes.RETURN:

-                break;

-            case Opcodes.ACONST_NULL:

-                push(NULL);

-                break;

-            case Opcodes.ICONST_M1:

-            case Opcodes.ICONST_0:

-            case Opcodes.ICONST_1:

-            case Opcodes.ICONST_2:

-            case Opcodes.ICONST_3:

-            case Opcodes.ICONST_4:

-            case Opcodes.ICONST_5:

-            case Opcodes.BIPUSH:

-            case Opcodes.SIPUSH:

-            case Opcodes.ILOAD:

-                push(INTEGER);

-                break;

-            case Opcodes.LCONST_0:

-            case Opcodes.LCONST_1:

-            case Opcodes.LLOAD:

-                push(LONG);

-                push(TOP);

-                break;

-            case Opcodes.FCONST_0:

-            case Opcodes.FCONST_1:

-            case Opcodes.FCONST_2:

-            case Opcodes.FLOAD:

-                push(FLOAT);

-                break;

-            case Opcodes.DCONST_0:

-            case Opcodes.DCONST_1:

-            case Opcodes.DLOAD:

-                push(DOUBLE);

-                push(TOP);

-                break;

-            case Opcodes.LDC:

-                switch (item.type) {

-                    case ClassWriter.INT:

-                        push(INTEGER);

-                        break;

-                    case ClassWriter.LONG:

-                        push(LONG);

-                        push(TOP);

-                        break;

-                    case ClassWriter.FLOAT:

-                        push(FLOAT);

-                        break;

-                    case ClassWriter.DOUBLE:

-                        push(DOUBLE);

-                        push(TOP);

-                        break;

-                    case ClassWriter.CLASS:

-                        push(OBJECT | cw.addType("java/lang/Class"));

-                        break;

-                    // case ClassWriter.STR:

-                    default:

-                        push(OBJECT | cw.addType("java/lang/String"));

-                }

-                break;

-            case Opcodes.ALOAD:

-                push(get(arg));

-                break;

-            case Opcodes.IALOAD:

-            case Opcodes.BALOAD:

-            case Opcodes.CALOAD:

-            case Opcodes.SALOAD:

-                pop(2);

-                push(INTEGER);

-                break;

-            case Opcodes.LALOAD:

-            case Opcodes.D2L:

-                pop(2);

-                push(LONG);

-                push(TOP);

-                break;

-            case Opcodes.FALOAD:

-                pop(2);

-                push(FLOAT);

-                break;

-            case Opcodes.DALOAD:

-            case Opcodes.L2D:

-                pop(2);

-                push(DOUBLE);

-                push(TOP);

-                break;

-            case Opcodes.AALOAD:

-                pop(1);

-                t1 = pop();

-                push(ELEMENT_OF + t1);

-                break;

-            case Opcodes.ISTORE:

-            case Opcodes.FSTORE:

-            case Opcodes.ASTORE:

-                t1 = pop();

-                set(arg, t1);

-                if (arg > 0) {

-                    t2 = get(arg - 1);

-                    // if t2 is of kind STACK or LOCAL we cannot know its size!

-                    if (t2 == LONG || t2 == DOUBLE) {

-                        set(arg - 1, TOP);

-                    }

-                }

-                break;

-            case Opcodes.LSTORE:

-            case Opcodes.DSTORE:

-                pop(1);

-                t1 = pop();

-                set(arg, t1);

-                set(arg + 1, TOP);

-                if (arg > 0) {

-                    t2 = get(arg - 1);

-                    // if t2 is of kind STACK or LOCAL we cannot know its size!

-                    if (t2 == LONG || t2 == DOUBLE) {

-                        set(arg - 1, TOP);

-                    }

-                }

-                break;

-            case Opcodes.IASTORE:

-            case Opcodes.BASTORE:

-            case Opcodes.CASTORE:

-            case Opcodes.SASTORE:

-            case Opcodes.FASTORE:

-            case Opcodes.AASTORE:

-                pop(3);

-                break;

-            case Opcodes.LASTORE:

-            case Opcodes.DASTORE:

-                pop(4);

-                break;

-            case Opcodes.POP:

-            case Opcodes.IFEQ:

-            case Opcodes.IFNE:

-            case Opcodes.IFLT:

-            case Opcodes.IFGE:

-            case Opcodes.IFGT:

-            case Opcodes.IFLE:

-            case Opcodes.IRETURN:

-            case Opcodes.FRETURN:

-            case Opcodes.ARETURN:

-            case Opcodes.TABLESWITCH:

-            case Opcodes.LOOKUPSWITCH:

-            case Opcodes.ATHROW:

-            case Opcodes.MONITORENTER:

-            case Opcodes.MONITOREXIT:

-            case Opcodes.IFNULL:

-            case Opcodes.IFNONNULL:

-                pop(1);

-                break;

-            case Opcodes.POP2:

-            case Opcodes.IF_ICMPEQ:

-            case Opcodes.IF_ICMPNE:

-            case Opcodes.IF_ICMPLT:

-            case Opcodes.IF_ICMPGE:

-            case Opcodes.IF_ICMPGT:

-            case Opcodes.IF_ICMPLE:

-            case Opcodes.IF_ACMPEQ:

-            case Opcodes.IF_ACMPNE:

-            case Opcodes.LRETURN:

-            case Opcodes.DRETURN:

-                pop(2);

-                break;

-            case Opcodes.DUP:

-                t1 = pop();

-                push(t1);

-                push(t1);

-                break;

-            case Opcodes.DUP_X1:

-                t1 = pop();

-                t2 = pop();

-                push(t1);

-                push(t2);

-                push(t1);

-                break;

-            case Opcodes.DUP_X2:

-                t1 = pop();

-                t2 = pop();

-                t3 = pop();

-                push(t1);

-                push(t3);

-                push(t2);

-                push(t1);

-                break;

-            case Opcodes.DUP2:

-                t1 = pop();

-                t2 = pop();

-                push(t2);

-                push(t1);

-                push(t2);

-                push(t1);

-                break;

-            case Opcodes.DUP2_X1:

-                t1 = pop();

-                t2 = pop();

-                t3 = pop();

-                push(t2);

-                push(t1);

-                push(t3);

-                push(t2);

-                push(t1);

-                break;

-            case Opcodes.DUP2_X2:

-                t1 = pop();

-                t2 = pop();

-                t3 = pop();

-                t4 = pop();

-                push(t2);

-                push(t1);

-                push(t4);

-                push(t3);

-                push(t2);

-                push(t1);

-                break;

-            case Opcodes.SWAP:

-                t1 = pop();

-                t2 = pop();

-                push(t1);

-                push(t2);

-                break;

-            case Opcodes.IADD:

-            case Opcodes.ISUB:

-            case Opcodes.IMUL:

-            case Opcodes.IDIV:

-            case Opcodes.IREM:

-            case Opcodes.IAND:

-            case Opcodes.IOR:

-            case Opcodes.IXOR:

-            case Opcodes.ISHL:

-            case Opcodes.ISHR:

-            case Opcodes.IUSHR:

-            case Opcodes.L2I:

-            case Opcodes.D2I:

-            case Opcodes.FCMPL:

-            case Opcodes.FCMPG:

-                pop(2);

-                push(INTEGER);

-                break;

-            case Opcodes.LADD:

-            case Opcodes.LSUB:

-            case Opcodes.LMUL:

-            case Opcodes.LDIV:

-            case Opcodes.LREM:

-            case Opcodes.LAND:

-            case Opcodes.LOR:

-            case Opcodes.LXOR:

-                pop(4);

-                push(LONG);

-                push(TOP);

-                break;

-            case Opcodes.FADD:

-            case Opcodes.FSUB:

-            case Opcodes.FMUL:

-            case Opcodes.FDIV:

-            case Opcodes.FREM:

-            case Opcodes.L2F:

-            case Opcodes.D2F:

-                pop(2);

-                push(FLOAT);

-                break;

-            case Opcodes.DADD:

-            case Opcodes.DSUB:

-            case Opcodes.DMUL:

-            case Opcodes.DDIV:

-            case Opcodes.DREM:

-                pop(4);

-                push(DOUBLE);

-                push(TOP);

-                break;

-            case Opcodes.LSHL:

-            case Opcodes.LSHR:

-            case Opcodes.LUSHR:

-                pop(3);

-                push(LONG);

-                push(TOP);

-                break;

-            case Opcodes.IINC:

-                set(arg, INTEGER);

-                break;

-            case Opcodes.I2L:

-            case Opcodes.F2L:

-                pop(1);

-                push(LONG);

-                push(TOP);

-                break;

-            case Opcodes.I2F:

-                pop(1);

-                push(FLOAT);

-                break;

-            case Opcodes.I2D:

-            case Opcodes.F2D:

-                pop(1);

-                push(DOUBLE);

-                push(TOP);

-                break;

-            case Opcodes.F2I:

-            case Opcodes.ARRAYLENGTH:

-            case Opcodes.INSTANCEOF:

-                pop(1);

-                push(INTEGER);

-                break;

-            case Opcodes.LCMP:

-            case Opcodes.DCMPL:

-            case Opcodes.DCMPG:

-                pop(4);

-                push(INTEGER);

-                break;

-            case Opcodes.JSR:

-            case Opcodes.RET:

-                throw new RuntimeException("JSR/RET are not supported with computeFrames option");

-            case Opcodes.GETSTATIC:

-                push(cw, item.strVal3);

-                break;

-            case Opcodes.PUTSTATIC:

-                pop(item.strVal3);

-                break;

-            case Opcodes.GETFIELD:

-                pop(1);

-                push(cw, item.strVal3);

-                break;

-            case Opcodes.PUTFIELD:

-                pop(item.strVal3);

-                pop();

-                break;

-            case Opcodes.INVOKEVIRTUAL:

-            case Opcodes.INVOKESPECIAL:

-            case Opcodes.INVOKESTATIC:

-            case Opcodes.INVOKEINTERFACE:

-                pop(item.strVal3);

-                if (opcode != Opcodes.INVOKESTATIC) {

-                    t1 = pop();

-                    if (opcode == Opcodes.INVOKESPECIAL

-                            && item.strVal2.charAt(0) == '<')

-                    {

-                        init(t1);

-                    }

-                }

-                push(cw, item.strVal3);

-                break;

-            case Opcodes.NEW:

-                push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));

-                break;

-            case Opcodes.NEWARRAY:

-                pop();

-                switch (arg) {

-                    case Opcodes.T_BOOLEAN:

-                        push(ARRAY_OF | BOOLEAN);

-                        break;

-                    case Opcodes.T_CHAR:

-                        push(ARRAY_OF | CHAR);

-                        break;

-                    case Opcodes.T_BYTE:

-                        push(ARRAY_OF | BYTE);

-                        break;

-                    case Opcodes.T_SHORT:

-                        push(ARRAY_OF | SHORT);

-                        break;

-                    case Opcodes.T_INT:

-                        push(ARRAY_OF | INTEGER);

-                        break;

-                    case Opcodes.T_FLOAT:

-                        push(ARRAY_OF | FLOAT);

-                        break;

-                    case Opcodes.T_DOUBLE:

-                        push(ARRAY_OF | DOUBLE);

-                        break;

-                    // case Opcodes.T_LONG:

-                    default:

-                        push(ARRAY_OF | LONG);

-                        break;

-                }

-                break;

-            case Opcodes.ANEWARRAY:

-                String s = item.strVal1;

-                pop();

-                if (s.charAt(0) == '[') {

-                    push(cw, '[' + s);

-                } else {

-                    push(ARRAY_OF | OBJECT | cw.addType(s));

-                }

-                break;

-            case Opcodes.CHECKCAST:

-                s = item.strVal1;

-                pop();

-                if (s.charAt(0) == '[') {

-                    push(cw, s);

-                } else {

-                    push(OBJECT | cw.addType(s));

-                }

-                break;

-            // case Opcodes.MULTIANEWARRAY:

-            default:

-                pop(arg);

-                push(cw, item.strVal1);

-                break;

-        }

-    }

-

-    /**

-     * Merges the input frame of the given basic block with the input and output

-     * frames of this basic block. Returns <tt>true</tt> if the input frame of

-     * the given label has been changed by this operation.

-     * 

-     * @param cw the ClassWriter to which this label belongs.

-     * @param frame the basic block whose input frame must be updated.

-     * @param edge the kind of the {@link Edge} between this label and 'label'.

-     *        See {@link Edge#info}.

-     * @return <tt>true</tt> if the input frame of the given label has been

-     *         changed by this operation.

-     */

-    boolean merge(final ClassWriter cw, final Frame frame, final int edge) {

-        boolean changed = false;

-        int i, s, dim, kind, t;

-

-        int nLocal = inputLocals.length;

-        int nStack = inputStack.length;

-        if (frame.inputLocals == null) {

-            frame.inputLocals = new int[nLocal];

-            changed = true;

-        }

-

-        for (i = 0; i < nLocal; ++i) {

-            if (outputLocals != null && i < outputLocals.length) {

-                s = outputLocals[i];

-                if (s == 0) {

-                    t = inputLocals[i];

-                } else {

-                    dim = s & DIM;

-                    kind = s & KIND;

-                    if (kind == LOCAL) {

-                        t = dim + inputLocals[s & VALUE];

-                    } else if (kind == STACK) {

-                        t = dim + inputStack[nStack - (s & VALUE)];

-                    } else {

-                        t = s;

-                    }

-                }

-            } else {

-                t = inputLocals[i];

-            }

-            if (initializations != null) {

-                t = init(cw, t);

-            }

-            changed |= merge(cw, t, frame.inputLocals, i);

-        }

-

-        if (edge > 0) {

-            for (i = 0; i < nLocal; ++i) {

-                t = inputLocals[i];

-                changed |= merge(cw, t, frame.inputLocals, i);

-            }

-            if (frame.inputStack == null) {

-                frame.inputStack = new int[1];

-                changed = true;

-            }

-            changed |= merge(cw, edge, frame.inputStack, 0);

-            return changed;

-        }

-

-        int nInputStack = inputStack.length + owner.inputStackTop;

-        if (frame.inputStack == null) {

-            frame.inputStack = new int[nInputStack + outputStackTop];

-            changed = true;

-        }

-

-        for (i = 0; i < nInputStack; ++i) {

-            t = inputStack[i];

-            if (initializations != null) {

-                t = init(cw, t);

-            }

-            changed |= merge(cw, t, frame.inputStack, i);

-        }

-        for (i = 0; i < outputStackTop; ++i) {

-            s = outputStack[i];

-            dim = s & DIM;

-            kind = s & KIND;

-            if (kind == LOCAL) {

-                t = dim + inputLocals[s & VALUE];

-            } else if (kind == STACK) {

-                t = dim + inputStack[nStack - (s & VALUE)];

-            } else {

-                t = s;

-            }

-            if (initializations != null) {

-                t = init(cw, t);

-            }

-            changed |= merge(cw, t, frame.inputStack, nInputStack + i);

-        }

-        return changed;

-    }

-

-    /**

-     * Merges the type at the given index in the given type array with the given

-     * type. Returns <tt>true</tt> if the type array has been modified by this

-     * operation.

-     * 

-     * @param cw the ClassWriter to which this label belongs.

-     * @param t the type with which the type array element must be merged.

-     * @param types an array of types.

-     * @param index the index of the type that must be merged in 'types'.

-     * @return <tt>true</tt> if the type array has been modified by this

-     *         operation.

-     */

-    private static boolean merge(

-        final ClassWriter cw,

-        int t,

-        final int[] types,

-        final int index)

-    {

-        int u = types[index];

-        if (u == t) {

-            // if the types are equal, merge(u,t)=u, so there is no change

-            return false;

-        }

-        if ((t & ~DIM) == NULL) {

-            if (u == NULL) {

-                return false;

-            }

-            t = NULL;

-        }

-        if (u == 0) {

-            // if types[index] has never been assigned, merge(u,t)=t

-            types[index] = t;

-            return true;

-        }

-        int v;

-        if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {

-            // if u is a reference type of any dimension

-            if (t == NULL) {

-                // if t is the NULL type, merge(u,t)=u, so there is no change

-                return false;

-            } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {

-                if ((u & BASE_KIND) == OBJECT) {

-                    // if t is also a reference type, and if u and t have the

-                    // same dimension merge(u,t) = dim(t) | common parent of the

-                    // element types of u and t

-                    v = (t & DIM) | OBJECT

-                            | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);

-                } else {

-                    // if u and t are array types, but not with the same element

-                    // type, merge(u,t)=java/lang/Object

-                    v = OBJECT | cw.addType("java/lang/Object");

-                }

-            } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {

-                // if t is any other reference or array type,

-                // merge(u,t)=java/lang/Object

-                v = OBJECT | cw.addType("java/lang/Object");

-            } else {

-                // if t is any other type, merge(u,t)=TOP

-                v = TOP;

-            }

-        } else if (u == NULL) {

-            // if u is the NULL type, merge(u,t)=t,

-            // or TOP if t is not a reference type

-            v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;

-        } else {

-            // if u is any other type, merge(u,t)=TOP whatever t

-            v = TOP;

-        }

-        if (u != v) {

-            types[index] = v;

-            return true;

-        }

-        return false;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Handler.java b/cglib-and-asm/src/org/mockito/asm/Handler.java
deleted file mode 100644
index 09836cc..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Handler.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * Information about an exception handler block.

- * 

- * @author Eric Bruneton

- */

-class Handler {

-

-    /**

-     * Beginning of the exception handler's scope (inclusive).

-     */

-    Label start;

-

-    /**

-     * End of the exception handler's scope (exclusive).

-     */

-    Label end;

-

-    /**

-     * Beginning of the exception handler's code.

-     */

-    Label handler;

-

-    /**

-     * Internal name of the type of exceptions handled by this handler, or

-     * <tt>null</tt> to catch any exceptions.

-     */

-    String desc;

-

-    /**

-     * Constant pool index of the internal name of the type of exceptions

-     * handled by this handler, or 0 to catch any exceptions.

-     */

-    int type;

-

-    /**

-     * Next exception handler block info.

-     */

-    Handler next;

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Item.java b/cglib-and-asm/src/org/mockito/asm/Item.java
deleted file mode 100644
index 90fdbfe..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Item.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A constant pool item. Constant pool items can be created with the 'newXXX'

- * methods in the {@link ClassWriter} class.

- * 

- * @author Eric Bruneton

- */

-final class Item {

-

-    /**

-     * Index of this item in the constant pool.

-     */

-    int index;

-

-    /**

-     * Type of this constant pool item. A single class is used to represent all

-     * constant pool item types, in order to minimize the bytecode size of this

-     * package. The value of this field is one of {@link ClassWriter#INT},

-     * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},

-     * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},

-     * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},

-     * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},

-     * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}.

-     * 

-     * Special Item types are used for Items that are stored in the ClassWriter

-     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to

-     * avoid clashes with normal constant pool items in the ClassWriter constant

-     * pool's hash table. These special item types are

-     * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and

-     * {@link ClassWriter#TYPE_MERGED}.

-     */

-    int type;

-

-    /**

-     * Value of this item, for an integer item.

-     */

-    int intVal;

-

-    /**

-     * Value of this item, for a long item.

-     */

-    long longVal;

-

-    /**

-     * First part of the value of this item, for items that do not hold a

-     * primitive value.

-     */

-    String strVal1;

-

-    /**

-     * Second part of the value of this item, for items that do not hold a

-     * primitive value.

-     */

-    String strVal2;

-

-    /**

-     * Third part of the value of this item, for items that do not hold a

-     * primitive value.

-     */

-    String strVal3;

-

-    /**

-     * The hash code value of this constant pool item.

-     */

-    int hashCode;

-

-    /**

-     * Link to another constant pool item, used for collision lists in the

-     * constant pool's hash table.

-     */

-    Item next;

-

-    /**

-     * Constructs an uninitialized {@link Item}.

-     */

-    Item() {

-    }

-

-    /**

-     * Constructs an uninitialized {@link Item} for constant pool element at

-     * given position.

-     * 

-     * @param index index of the item to be constructed.

-     */

-    Item(final int index) {

-        this.index = index;

-    }

-

-    /**

-     * Constructs a copy of the given item.

-     * 

-     * @param index index of the item to be constructed.

-     * @param i the item that must be copied into the item to be constructed.

-     */

-    Item(final int index, final Item i) {

-        this.index = index;

-        type = i.type;

-        intVal = i.intVal;

-        longVal = i.longVal;

-        strVal1 = i.strVal1;

-        strVal2 = i.strVal2;

-        strVal3 = i.strVal3;

-        hashCode = i.hashCode;

-    }

-

-    /**

-     * Sets this item to an integer item.

-     * 

-     * @param intVal the value of this item.

-     */

-    void set(final int intVal) {

-        this.type = ClassWriter.INT;

-        this.intVal = intVal;

-        this.hashCode = 0x7FFFFFFF & (type + intVal);

-    }

-

-    /**

-     * Sets this item to a long item.

-     * 

-     * @param longVal the value of this item.

-     */

-    void set(final long longVal) {

-        this.type = ClassWriter.LONG;

-        this.longVal = longVal;

-        this.hashCode = 0x7FFFFFFF & (type + (int) longVal);

-    }

-

-    /**

-     * Sets this item to a float item.

-     * 

-     * @param floatVal the value of this item.

-     */

-    void set(final float floatVal) {

-        this.type = ClassWriter.FLOAT;

-        this.intVal = Float.floatToRawIntBits(floatVal);

-        this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);

-    }

-

-    /**

-     * Sets this item to a double item.

-     * 

-     * @param doubleVal the value of this item.

-     */

-    void set(final double doubleVal) {

-        this.type = ClassWriter.DOUBLE;

-        this.longVal = Double.doubleToRawLongBits(doubleVal);

-        this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);

-    }

-

-    /**

-     * Sets this item to an item that do not hold a primitive value.

-     * 

-     * @param type the type of this item.

-     * @param strVal1 first part of the value of this item.

-     * @param strVal2 second part of the value of this item.

-     * @param strVal3 third part of the value of this item.

-     */

-    void set(

-        final int type,

-        final String strVal1,

-        final String strVal2,

-        final String strVal3)

-    {

-        this.type = type;

-        this.strVal1 = strVal1;

-        this.strVal2 = strVal2;

-        this.strVal3 = strVal3;

-        switch (type) {

-            case ClassWriter.UTF8:

-            case ClassWriter.STR:

-            case ClassWriter.CLASS:

-            case ClassWriter.TYPE_NORMAL:

-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());

-                return;

-            case ClassWriter.NAME_TYPE:

-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()

-                        * strVal2.hashCode());

-                return;

-                // ClassWriter.FIELD:

-                // ClassWriter.METH:

-                // ClassWriter.IMETH:

-            default:

-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()

-                        * strVal2.hashCode() * strVal3.hashCode());

-        }

-    }

-

-    /**

-     * Indicates if the given item is equal to this one.

-     * 

-     * @param i the item to be compared to this one.

-     * @return <tt>true</tt> if the given item if equal to this one,

-     *         <tt>false</tt> otherwise.

-     */

-    boolean isEqualTo(final Item i) {

-        if (i.type == type) {

-            switch (type) {

-                case ClassWriter.INT:

-                case ClassWriter.FLOAT:

-                    return i.intVal == intVal;

-                case ClassWriter.TYPE_MERGED:

-                case ClassWriter.LONG:

-                case ClassWriter.DOUBLE:

-                    return i.longVal == longVal;

-                case ClassWriter.UTF8:

-                case ClassWriter.STR:

-                case ClassWriter.CLASS:

-                case ClassWriter.TYPE_NORMAL:

-                    return i.strVal1.equals(strVal1);

-                case ClassWriter.TYPE_UNINIT:

-                    return i.intVal == intVal && i.strVal1.equals(strVal1);

-                case ClassWriter.NAME_TYPE:

-                    return i.strVal1.equals(strVal1)

-                            && i.strVal2.equals(strVal2);

-                    // ClassWriter.FIELD:

-                    // ClassWriter.METH:

-                    // ClassWriter.IMETH:

-                default:

-                    return i.strVal1.equals(strVal1)

-                            && i.strVal2.equals(strVal2)

-                            && i.strVal3.equals(strVal3);

-            }

-        }

-        return false;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Label.java b/cglib-and-asm/src/org/mockito/asm/Label.java
deleted file mode 100644
index 3394ca8..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Label.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A label represents a position in the bytecode of a method. Labels are used

- * for jump, goto, and switch instructions, and for try catch blocks.

- * 

- * @author Eric Bruneton

- */

-public class Label {

-

-    /**

-     * Indicates if this label is only used for debug attributes. Such a label

-     * is not the start of a basic block, the target of a jump instruction, or

-     * an exception handler. It can be safely ignored in control flow graph

-     * analysis algorithms (for optimization purposes).

-     */

-    static final int DEBUG = 1;

-

-    /**

-     * Indicates if the position of this label is known.

-     */

-    static final int RESOLVED = 2;

-

-    /**

-     * Indicates if this label has been updated, after instruction resizing.

-     */

-    static final int RESIZED = 4;

-

-    /**

-     * Indicates if this basic block has been pushed in the basic block stack.

-     * See {@link MethodWriter#visitMaxs visitMaxs}.

-     */

-    static final int PUSHED = 8;

-

-    /**

-     * Indicates if this label is the target of a jump instruction, or the start

-     * of an exception handler.

-     */

-    static final int TARGET = 16;

-

-    /**

-     * Indicates if a stack map frame must be stored for this label.

-     */

-    static final int STORE = 32;

-

-    /**

-     * Indicates if this label corresponds to a reachable basic block.

-     */

-    static final int REACHABLE = 64;

-

-    /**

-     * Indicates if this basic block ends with a JSR instruction.

-     */

-    static final int JSR = 128;

-

-    /**

-     * Indicates if this basic block ends with a RET instruction.

-     */

-    static final int RET = 256;

-

-    /**

-     * Indicates if this basic block is the start of a subroutine.

-     */

-    static final int SUBROUTINE = 512;

-

-    /**

-     * Indicates if this subroutine basic block has been visited.

-     */

-    static final int VISITED = 1024;

-

-    /**

-     * Field used to associate user information to a label. Warning: this field

-     * is used by the ASM tree package. In order to use it with the ASM tree

-     * package you must override the {@link 

-     * org.mockito.asm.tree.MethodNode#getLabelNode} method.

-     */

-    public Object info;

-

-    /**

-     * Flags that indicate the status of this label.

-     * 

-     * @see #DEBUG

-     * @see #RESOLVED

-     * @see #RESIZED

-     * @see #PUSHED

-     * @see #TARGET

-     * @see #STORE

-     * @see #REACHABLE

-     * @see #JSR

-     * @see #RET

-     */

-    int status;

-

-    /**

-     * The line number corresponding to this label, if known.

-     */

-    int line;

-

-    /**

-     * The position of this label in the code, if known.

-     */

-    int position;

-

-    /**

-     * Number of forward references to this label, times two.

-     */

-    private int referenceCount;

-

-    /**

-     * Informations about forward references. Each forward reference is

-     * described by two consecutive integers in this array: the first one is the

-     * position of the first byte of the bytecode instruction that contains the

-     * forward reference, while the second is the position of the first byte of

-     * the forward reference itself. In fact the sign of the first integer

-     * indicates if this reference uses 2 or 4 bytes, and its absolute value

-     * gives the position of the bytecode instruction. This array is also used

-     * as a bitset to store the subroutines to which a basic block belongs. This

-     * information is needed in {@linked  MethodWriter#visitMaxs}, after all

-     * forward references have been resolved. Hence the same array can be used

-     * for both purposes without problems.

-     */

-    private int[] srcAndRefPositions;

-

-    // ------------------------------------------------------------------------

-

-    /*

-     * Fields for the control flow and data flow graph analysis algorithms (used

-     * to compute the maximum stack size or the stack map frames). A control

-     * flow graph contains one node per "basic block", and one edge per "jump"

-     * from one basic block to another. Each node (i.e., each basic block) is

-     * represented by the Label object that corresponds to the first instruction

-     * of this basic block. Each node also stores the list of its successors in

-     * the graph, as a linked list of Edge objects.

-     * 

-     * The control flow analysis algorithms used to compute the maximum stack

-     * size or the stack map frames are similar and use two steps. The first

-     * step, during the visit of each instruction, builds information about the

-     * state of the local variables and the operand stack at the end of each

-     * basic block, called the "output frame", <i>relatively</i> to the frame

-     * state at the beginning of the basic block, which is called the "input

-     * frame", and which is <i>unknown</i> during this step. The second step,

-     * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that

-     * computes information about the input frame of each basic block, from the

-     * input state of the first basic block (known from the method signature),

-     * and by the using the previously computed relative output frames.

-     * 

-     * The algorithm used to compute the maximum stack size only computes the

-     * relative output and absolute input stack heights, while the algorithm

-     * used to compute stack map frames computes relative output frames and

-     * absolute input frames.

-     */

-

-    /**

-     * Start of the output stack relatively to the input stack. The exact

-     * semantics of this field depends on the algorithm that is used.

-     * 

-     * When only the maximum stack size is computed, this field is the number of

-     * elements in the input stack.

-     * 

-     * When the stack map frames are completely computed, this field is the

-     * offset of the first output stack element relatively to the top of the

-     * input stack. This offset is always negative or null. A null offset means

-     * that the output stack must be appended to the input stack. A -n offset

-     * means that the first n output stack elements must replace the top n input

-     * stack elements, and that the other elements must be appended to the input

-     * stack.

-     */

-    int inputStackTop;

-

-    /**

-     * Maximum height reached by the output stack, relatively to the top of the

-     * input stack. This maximum is always positive or null.

-     */

-    int outputStackMax;

-

-    /**

-     * Information about the input and output stack map frames of this basic

-     * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}

-     * option is used.

-     */

-    Frame frame;

-

-    /**

-     * The successor of this label, in the order they are visited. This linked

-     * list does not include labels used for debug info only. If

-     * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it

-     * does not contain successive labels that denote the same bytecode position

-     * (in this case only the first label appears in this list).

-     */

-    Label successor;

-

-    /**

-     * The successors of this node in the control flow graph. These successors

-     * are stored in a linked list of {@link Edge Edge} objects, linked to each

-     * other by their {@link Edge#next} field.

-     */

-    Edge successors;

-

-    /**

-     * The next basic block in the basic block stack. This stack is used in the

-     * main loop of the fix point algorithm used in the second step of the

-     * control flow analysis algorithms.

-     * 

-     * @see MethodWriter#visitMaxs

-     */

-    Label next;

-

-    // ------------------------------------------------------------------------

-    // Constructor

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a new label.

-     */

-    public Label() {

-    }

-

-    // ------------------------------------------------------------------------

-    // Methods to compute offsets and to manage forward references

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the offset corresponding to this label. This offset is computed

-     * from the start of the method's bytecode. <i>This method is intended for

-     * {@link Attribute} sub classes, and is normally not needed by class

-     * generators or adapters.</i>

-     * 

-     * @return the offset corresponding to this label.

-     * @throws IllegalStateException if this label is not resolved yet.

-     */

-    public int getOffset() {

-        if ((status & RESOLVED) == 0) {

-            throw new IllegalStateException("Label offset position has not been resolved yet");

-        }

-        return position;

-    }

-

-    /**

-     * Puts a reference to this label in the bytecode of a method. If the

-     * position of the label is known, the offset is computed and written

-     * directly. Otherwise, a null offset is written and a new forward reference

-     * is declared for this label.

-     * 

-     * @param owner the code writer that calls this method.

-     * @param out the bytecode of the method.

-     * @param source the position of first byte of the bytecode instruction that

-     *        contains this label.

-     * @param wideOffset <tt>true</tt> if the reference must be stored in 4

-     *        bytes, or <tt>false</tt> if it must be stored with 2 bytes.

-     * @throws IllegalArgumentException if this label has not been created by

-     *         the given code writer.

-     */

-    void put(

-        final MethodWriter owner,

-        final ByteVector out,

-        final int source,

-        final boolean wideOffset)

-    {

-        if ((status & RESOLVED) == 0) {

-            if (wideOffset) {

-                addReference(-1 - source, out.length);

-                out.putInt(-1);

-            } else {

-                addReference(source, out.length);

-                out.putShort(-1);

-            }

-        } else {

-            if (wideOffset) {

-                out.putInt(position - source);

-            } else {

-                out.putShort(position - source);

-            }

-        }

-    }

-

-    /**

-     * Adds a forward reference to this label. This method must be called only

-     * for a true forward reference, i.e. only if this label is not resolved

-     * yet. For backward references, the offset of the reference can be, and

-     * must be, computed and stored directly.

-     * 

-     * @param sourcePosition the position of the referencing instruction. This

-     *        position will be used to compute the offset of this forward

-     *        reference.

-     * @param referencePosition the position where the offset for this forward

-     *        reference must be stored.

-     */

-    private void addReference(

-        final int sourcePosition,

-        final int referencePosition)

-    {

-        if (srcAndRefPositions == null) {

-            srcAndRefPositions = new int[6];

-        }

-        if (referenceCount >= srcAndRefPositions.length) {

-            int[] a = new int[srcAndRefPositions.length + 6];

-            System.arraycopy(srcAndRefPositions,

-                    0,

-                    a,

-                    0,

-                    srcAndRefPositions.length);

-            srcAndRefPositions = a;

-        }

-        srcAndRefPositions[referenceCount++] = sourcePosition;

-        srcAndRefPositions[referenceCount++] = referencePosition;

-    }

-

-    /**

-     * Resolves all forward references to this label. This method must be called

-     * when this label is added to the bytecode of the method, i.e. when its

-     * position becomes known. This method fills in the blanks that where left

-     * in the bytecode by each forward reference previously added to this label.

-     * 

-     * @param owner the code writer that calls this method.

-     * @param position the position of this label in the bytecode.

-     * @param data the bytecode of the method.

-     * @return <tt>true</tt> if a blank that was left for this label was to

-     *         small to store the offset. In such a case the corresponding jump

-     *         instruction is replaced with a pseudo instruction (using unused

-     *         opcodes) using an unsigned two bytes offset. These pseudo

-     *         instructions will need to be replaced with true instructions with

-     *         wider offsets (4 bytes instead of 2). This is done in

-     *         {@link MethodWriter#resizeInstructions}.

-     * @throws IllegalArgumentException if this label has already been resolved,

-     *         or if it has not been created by the given code writer.

-     */

-    boolean resolve(

-        final MethodWriter owner,

-        final int position,

-        final byte[] data)

-    {

-        boolean needUpdate = false;

-        this.status |= RESOLVED;

-        this.position = position;

-        int i = 0;

-        while (i < referenceCount) {

-            int source = srcAndRefPositions[i++];

-            int reference = srcAndRefPositions[i++];

-            int offset;

-            if (source >= 0) {

-                offset = position - source;

-                if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {

-                    /*

-                     * changes the opcode of the jump instruction, in order to

-                     * be able to find it later (see resizeInstructions in

-                     * MethodWriter). These temporary opcodes are similar to

-                     * jump instruction opcodes, except that the 2 bytes offset

-                     * is unsigned (and can therefore represent values from 0 to

-                     * 65535, which is sufficient since the size of a method is

-                     * limited to 65535 bytes).

-                     */

-                    int opcode = data[reference - 1] & 0xFF;

-                    if (opcode <= Opcodes.JSR) {

-                        // changes IFEQ ... JSR to opcodes 202 to 217

-                        data[reference - 1] = (byte) (opcode + 49);

-                    } else {

-                        // changes IFNULL and IFNONNULL to opcodes 218 and 219

-                        data[reference - 1] = (byte) (opcode + 20);

-                    }

-                    needUpdate = true;

-                }

-                data[reference++] = (byte) (offset >>> 8);

-                data[reference] = (byte) offset;

-            } else {

-                offset = position + source + 1;

-                data[reference++] = (byte) (offset >>> 24);

-                data[reference++] = (byte) (offset >>> 16);

-                data[reference++] = (byte) (offset >>> 8);

-                data[reference] = (byte) offset;

-            }

-        }

-        return needUpdate;

-    }

-

-    /**

-     * Returns the first label of the series to which this label belongs. For an

-     * isolated label or for the first label in a series of successive labels,

-     * this method returns the label itself. For other labels it returns the

-     * first label of the series.

-     * 

-     * @return the first label of the series to which this label belongs.

-     */

-    Label getFirst() {

-        return !ClassReader.FRAMES || frame == null ? this : frame.owner;

-    }

-

-    // ------------------------------------------------------------------------

-    // Methods related to subroutines

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns true is this basic block belongs to the given subroutine.

-     * 

-     * @param id a subroutine id.

-     * @return true is this basic block belongs to the given subroutine.

-     */

-    boolean inSubroutine(final long id) {

-        if ((status & Label.VISITED) != 0) {

-            return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;

-        }

-        return false;

-    }

-

-    /**

-     * Returns true if this basic block and the given one belong to a common

-     * subroutine.

-     * 

-     * @param block another basic block.

-     * @return true if this basic block and the given one belong to a common

-     *         subroutine.

-     */

-    boolean inSameSubroutine(final Label block) {

-        for (int i = 0; i < srcAndRefPositions.length; ++i) {

-            if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {

-                return true;

-            }

-        }

-        return false;

-    }

-

-    /**

-     * Marks this basic block as belonging to the given subroutine.

-     * 

-     * @param id a subroutine id.

-     * @param nbSubroutines the total number of subroutines in the method.

-     */

-    void addToSubroutine(final long id, final int nbSubroutines) {

-        if ((status & VISITED) == 0) {

-            status |= VISITED;

-            srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1];

-        }

-        srcAndRefPositions[(int) (id >>> 32)] |= (int) id;

-    }

-    

-    /**

-     * Finds the basic blocks that belong to a given subroutine, and marks these

-     * blocks as belonging to this subroutine. This recursive method follows the

-     * control flow graph to find all the blocks that are reachable from the

-     * current block WITHOUT following any JSR target.

-     * 

-     * @param JSR a JSR block that jumps to this subroutine. If this JSR is not

-     *        null it is added to the successor of the RET blocks found in the

-     *        subroutine.

-     * @param id the id of this subroutine.

-     * @param nbSubroutines the total number of subroutines in the method.

-     */

-    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)

-    {

-        if (JSR != null) {

-            if ((status & VISITED) != 0) {

-                return;

-            }

-            status |= VISITED;

-            // adds JSR to the successors of this block, if it is a RET block

-            if ((status & RET) != 0) {

-                if (!inSameSubroutine(JSR)) {

-                    Edge e = new Edge();

-                    e.info = inputStackTop;

-                    e.successor = JSR.successors.successor;

-                    e.next = successors;

-                    successors = e;

-                }

-            }

-        } else {

-            // if this block already belongs to subroutine 'id', returns

-            if (inSubroutine(id)) {

-                return;

-            }

-            // marks this block as belonging to subroutine 'id'

-            addToSubroutine(id, nbSubroutines);            

-        }

-        // calls this method recursively on each successor, except JSR targets

-        Edge e = successors;

-        while (e != null) {

-            // if this block is a JSR block, then 'successors.next' leads

-            // to the JSR target (see {@link #visitJumpInsn}) and must therefore

-            // not be followed

-            if ((status & Label.JSR) == 0 || e != successors.next) {

-                e.successor.visitSubroutine(JSR, id, nbSubroutines);

-            }

-            e = e.next;

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Overriden Object methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns a string representation of this label.

-     * 

-     * @return a string representation of this label.

-     */

-    public String toString() {

-        return "L" + System.identityHashCode(this);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/MethodAdapter.java b/cglib-and-asm/src/org/mockito/asm/MethodAdapter.java
deleted file mode 100644
index 56b3be8..0000000
--- a/cglib-and-asm/src/org/mockito/asm/MethodAdapter.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * An empty {@link MethodVisitor} that delegates to another

- * {@link MethodVisitor}. This class can be used as a super class to quickly

- * implement usefull method adapter classes, just by overriding the necessary

- * methods.

- * 

- * @author Eric Bruneton

- */

-public class MethodAdapter implements MethodVisitor {

-

-    /**

-     * The {@link MethodVisitor} to which this adapter delegates calls.

-     */

-    protected MethodVisitor mv;

-

-    /**

-     * Constructs a new {@link MethodAdapter} object.

-     * 

-     * @param mv the code visitor to which this adapter must delegate calls.

-     */

-    public MethodAdapter(final MethodVisitor mv) {

-        this.mv = mv;

-    }

-

-    public AnnotationVisitor visitAnnotationDefault() {

-        return mv.visitAnnotationDefault();

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        return mv.visitAnnotation(desc, visible);

-    }

-

-    public AnnotationVisitor visitParameterAnnotation(

-        final int parameter,

-        final String desc,

-        final boolean visible)

-    {

-        return mv.visitParameterAnnotation(parameter, desc, visible);

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        mv.visitAttribute(attr);

-    }

-

-    public void visitCode() {

-        mv.visitCode();

-    }

-

-    public void visitFrame(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        mv.visitFrame(type, nLocal, local, nStack, stack);

-    }

-

-    public void visitInsn(final int opcode) {

-        mv.visitInsn(opcode);

-    }

-

-    public void visitIntInsn(final int opcode, final int operand) {

-        mv.visitIntInsn(opcode, operand);

-    }

-

-    public void visitVarInsn(final int opcode, final int var) {

-        mv.visitVarInsn(opcode, var);

-    }

-

-    public void visitTypeInsn(final int opcode, final String type) {

-        mv.visitTypeInsn(opcode, type);

-    }

-

-    public void visitFieldInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        mv.visitFieldInsn(opcode, owner, name, desc);

-    }

-

-    public void visitMethodInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        mv.visitMethodInsn(opcode, owner, name, desc);

-    }

-

-    public void visitJumpInsn(final int opcode, final Label label) {

-        mv.visitJumpInsn(opcode, label);

-    }

-

-    public void visitLabel(final Label label) {

-        mv.visitLabel(label);

-    }

-

-    public void visitLdcInsn(final Object cst) {

-        mv.visitLdcInsn(cst);

-    }

-

-    public void visitIincInsn(final int var, final int increment) {

-        mv.visitIincInsn(var, increment);

-    }

-

-    public void visitTableSwitchInsn(

-        final int min,

-        final int max,

-        final Label dflt,

-        final Label[] labels)

-    {

-        mv.visitTableSwitchInsn(min, max, dflt, labels);

-    }

-

-    public void visitLookupSwitchInsn(

-        final Label dflt,

-        final int[] keys,

-        final Label[] labels)

-    {

-        mv.visitLookupSwitchInsn(dflt, keys, labels);

-    }

-

-    public void visitMultiANewArrayInsn(final String desc, final int dims) {

-        mv.visitMultiANewArrayInsn(desc, dims);

-    }

-

-    public void visitTryCatchBlock(

-        final Label start,

-        final Label end,

-        final Label handler,

-        final String type)

-    {

-        mv.visitTryCatchBlock(start, end, handler, type);

-    }

-

-    public void visitLocalVariable(

-        final String name,

-        final String desc,

-        final String signature,

-        final Label start,

-        final Label end,

-        final int index)

-    {

-        mv.visitLocalVariable(name, desc, signature, start, end, index);

-    }

-

-    public void visitLineNumber(final int line, final Label start) {

-        mv.visitLineNumber(line, start);

-    }

-

-    public void visitMaxs(final int maxStack, final int maxLocals) {

-        mv.visitMaxs(maxStack, maxLocals);

-    }

-

-    public void visitEnd() {

-        mv.visitEnd();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/MethodVisitor.java b/cglib-and-asm/src/org/mockito/asm/MethodVisitor.java
deleted file mode 100644
index ee2a795..0000000
--- a/cglib-and-asm/src/org/mockito/asm/MethodVisitor.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A visitor to visit a Java method. The methods of this interface must be

- * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (

- * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |

- * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |

- * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |

- * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt>)* <tt>visitMaxs</tt> ]

- * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>

- * and <tt>visitLabel</tt> methods must be called in the sequential order of

- * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>

- * must be called <i>before</i> the labels passed as arguments have been

- * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>

- * methods must be called <i>after</i> the labels passed as arguments have been

- * visited.

- * 

- * @author Eric Bruneton

- */

-public interface MethodVisitor {

-

-    // -------------------------------------------------------------------------

-    // Annotations and non standard attributes

-    // -------------------------------------------------------------------------

-

-    /**

-     * Visits the default value of this annotation interface method.

-     * 

-     * @return a visitor to the visit the actual default value of this

-     *         annotation interface method, or <tt>null</tt> if this visitor

-     *         is not interested in visiting this default value. The 'name'

-     *         parameters passed to the methods of this annotation visitor are

-     *         ignored. Moreover, exacly one visit method must be called on this

-     *         annotation visitor, followed by visitEnd.

-     */

-    AnnotationVisitor visitAnnotationDefault();

-

-    /**

-     * Visits an annotation of this method.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values, or <tt>null</tt> if

-     *         this visitor is not interested in visiting this annotation.

-     */

-    AnnotationVisitor visitAnnotation(String desc, boolean visible);

-

-    /**

-     * Visits an annotation of a parameter this method.

-     * 

-     * @param parameter the parameter index.

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values, or <tt>null</tt> if

-     *         this visitor is not interested in visiting this annotation.

-     */

-    AnnotationVisitor visitParameterAnnotation(

-        int parameter,

-        String desc,

-        boolean visible);

-

-    /**

-     * Visits a non standard attribute of this method.

-     * 

-     * @param attr an attribute.

-     */

-    void visitAttribute(Attribute attr);

-

-    /**

-     * Starts the visit of the method's code, if any (i.e. non abstract method).

-     */

-    void visitCode();

-

-    /**

-     * Visits the current state of the local variables and operand stack

-     * elements. This method must(*) be called <i>just before</i> any

-     * instruction <b>i</b> that follows an unconditionnal branch instruction

-     * such as GOTO or THROW, that is the target of a jump instruction, or that

-     * starts an exception handler block. The visited types must describe the

-     * values of the local variables and of the operand stack elements <i>just

-     * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only

-     * for classes whose version is greater than or equal to

-     * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically

-     * "deltas" from the state of the previous frame (very first frame is

-     * implicitly defined by the method's parameters and access flags): <ul>

-     * <li>{@link Opcodes#F_SAME} representing frame with exactly the same

-     * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}

-     * representing frame with exactly the same locals as the previous frame and

-     * with single value on the stack (<code>nStack</code> is 1 and

-     * <code>stack[0]</code> contains value for the type of the stack item).</li>

-     * <li>{@link Opcodes#F_APPEND} representing frame with current locals are

-     * the same as the locals in the previous frame, except that additional

-     * locals are defined (<code>nLocal</code> is 1, 2 or 3 and

-     * <code>local</code> elements contains values representing added types).</li>

-     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are

-     * the same as the locals in the previous frame, except that the last 1-3

-     * locals are absent and with the empty stack (<code>nLocals</code> is 1,

-     * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame

-     * data.</li> </li> </ul>

-     * 

-     * @param type the type of this stack map frame. Must be

-     *        {@link Opcodes#F_NEW} for expanded frames, or

-     *        {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},

-     *        {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or

-     *        {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed

-     *        frames.

-     * @param nLocal the number of local variables in the visited frame.

-     * @param local the local variable types in this frame. This array must not

-     *        be modified. Primitive types are represented by

-     *        {@link Opcodes#TOP}, {@link Opcodes#INTEGER},

-     *        {@link Opcodes#FLOAT}, {@link Opcodes#LONG},

-     *        {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or

-     *        {@link Opcodes#UNINITIALIZED_THIS} (long and double are

-     *        represented by a single element). Reference types are represented

-     *        by String objects (representing internal names), and uninitialized 

-     *        types by Label objects (this label designates the NEW instruction 

-     *        that created this uninitialized value).

-     * @param nStack the number of operand stack elements in the visited frame.

-     * @param stack the operand stack types in this frame. This array must not

-     *        be modified. Its content has the same format as the "local" array.

-     */

-    void visitFrame(

-        int type,

-        int nLocal,

-        Object[] local,

-        int nStack,

-        Object[] stack);

-

-    // -------------------------------------------------------------------------

-    // Normal instructions

-    // -------------------------------------------------------------------------

-

-    /**

-     * Visits a zero operand instruction.

-     * 

-     * @param opcode the opcode of the instruction to be visited. This opcode is

-     *        either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,

-     *        ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0,

-     *        FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,

-     *        DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,

-     *        DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,

-     *        DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,

-     *        DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,

-     *        FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,

-     *        LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,

-     *        I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,

-     *        I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,

-     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,

-     *        MONITORENTER, or MONITOREXIT.

-     */

-    void visitInsn(int opcode);

-

-    /**

-     * Visits an instruction with a single int operand.

-     * 

-     * @param opcode the opcode of the instruction to be visited. This opcode is

-     *        either BIPUSH, SIPUSH or NEWARRAY.

-     * @param operand the operand of the instruction to be visited.<br> When

-     *        opcode is BIPUSH, operand value should be between Byte.MIN_VALUE

-     *        and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value

-     *        should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When

-     *        opcode is NEWARRAY, operand value should be one of

-     *        {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},

-     *        {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},

-     *        {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},

-     *        {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.

-     */

-    void visitIntInsn(int opcode, int operand);

-

-    /**

-     * Visits a local variable instruction. A local variable instruction is an

-     * instruction that loads or stores the value of a local variable.

-     * 

-     * @param opcode the opcode of the local variable instruction to be visited.

-     *        This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,

-     *        LSTORE, FSTORE, DSTORE, ASTORE or RET.

-     * @param var the operand of the instruction to be visited. This operand is

-     *        the index of a local variable.

-     */

-    void visitVarInsn(int opcode, int var);

-

-    /**

-     * Visits a type instruction. A type instruction is an instruction that

-     * takes the internal name of a class as parameter.

-     * 

-     * @param opcode the opcode of the type instruction to be visited. This

-     *        opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.

-     * @param type the operand of the instruction to be visited. This operand

-     *        must be the internal name of an object or array class (see {@link 

-     *        Type#getInternalName() getInternalName}).

-     */

-    void visitTypeInsn(int opcode, String type);

-

-    /**

-     * Visits a field instruction. A field instruction is an instruction that

-     * loads or stores the value of a field of an object.

-     * 

-     * @param opcode the opcode of the type instruction to be visited. This

-     *        opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.

-     * @param owner the internal name of the field's owner class (see {@link

-     *        Type#getInternalName() getInternalName}).

-     * @param name the field's name.

-     * @param desc the field's descriptor (see {@link Type Type}).

-     */

-    void visitFieldInsn(int opcode, String owner, String name, String desc);

-

-    /**

-     * Visits a method instruction. A method instruction is an instruction that

-     * invokes a method.

-     * 

-     * @param opcode the opcode of the type instruction to be visited. This

-     *        opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or

-     *        INVOKEINTERFACE.

-     * @param owner the internal name of the method's owner class (see {@link

-     *        Type#getInternalName() getInternalName}).

-     * @param name the method's name.

-     * @param desc the method's descriptor (see {@link Type Type}).

-     */

-    void visitMethodInsn(int opcode, String owner, String name, String desc);

-

-    /**

-     * Visits a jump instruction. A jump instruction is an instruction that may

-     * jump to another instruction.

-     * 

-     * @param opcode the opcode of the type instruction to be visited. This

-     *        opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,

-     *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,

-     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.

-     * @param label the operand of the instruction to be visited. This operand

-     *        is a label that designates the instruction to which the jump

-     *        instruction may jump.

-     */

-    void visitJumpInsn(int opcode, Label label);

-

-    /**

-     * Visits a label. A label designates the instruction that will be visited

-     * just after it.

-     * 

-     * @param label a {@link Label Label} object.

-     */

-    void visitLabel(Label label);

-

-    // -------------------------------------------------------------------------

-    // Special instructions

-    // -------------------------------------------------------------------------

-

-    /**

-     * Visits a LDC instruction.

-     * 

-     * @param cst the constant to be loaded on the stack. This parameter must be

-     *        a non null {@link Integer}, a {@link Float}, a {@link Long}, a

-     *        {@link Double} a {@link String} (or a {@link Type} for

-     *        <tt>.class</tt> constants, for classes whose version is 49.0 or

-     *        more).

-     */

-    void visitLdcInsn(Object cst);

-

-    /**

-     * Visits an IINC instruction.

-     * 

-     * @param var index of the local variable to be incremented.

-     * @param increment amount to increment the local variable by.

-     */

-    void visitIincInsn(int var, int increment);

-

-    /**

-     * Visits a TABLESWITCH instruction.

-     * 

-     * @param min the minimum key value.

-     * @param max the maximum key value.

-     * @param dflt beginning of the default handler block.

-     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is

-     *        the beginning of the handler block for the <tt>min + i</tt> key.

-     */

-    void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels);

-

-    /**

-     * Visits a LOOKUPSWITCH instruction.

-     * 

-     * @param dflt beginning of the default handler block.

-     * @param keys the values of the keys.

-     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is

-     *        the beginning of the handler block for the <tt>keys[i]</tt> key.

-     */

-    void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels);

-

-    /**

-     * Visits a MULTIANEWARRAY instruction.

-     * 

-     * @param desc an array type descriptor (see {@link Type Type}).

-     * @param dims number of dimensions of the array to allocate.

-     */

-    void visitMultiANewArrayInsn(String desc, int dims);

-

-    // -------------------------------------------------------------------------

-    // Exceptions table entries, debug information, max stack and max locals

-    // -------------------------------------------------------------------------

-

-    /**

-     * Visits a try catch block.

-     * 

-     * @param start beginning of the exception handler's scope (inclusive).

-     * @param end end of the exception handler's scope (exclusive).

-     * @param handler beginning of the exception handler's code.

-     * @param type internal name of the type of exceptions handled by the

-     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"

-     *        blocks).

-     * @throws IllegalArgumentException if one of the labels has already been

-     *         visited by this visitor (by the {@link #visitLabel visitLabel}

-     *         method).

-     */

-    void visitTryCatchBlock(Label start, Label end, Label handler, String type);

-

-    /**

-     * Visits a local variable declaration.

-     * 

-     * @param name the name of a local variable.

-     * @param desc the type descriptor of this local variable.

-     * @param signature the type signature of this local variable. May be

-     *        <tt>null</tt> if the local variable type does not use generic

-     *        types.

-     * @param start the first instruction corresponding to the scope of this

-     *        local variable (inclusive).

-     * @param end the last instruction corresponding to the scope of this local

-     *        variable (exclusive).

-     * @param index the local variable's index.

-     * @throws IllegalArgumentException if one of the labels has not already

-     *         been visited by this visitor (by the

-     *         {@link #visitLabel visitLabel} method).

-     */

-    void visitLocalVariable(

-        String name,

-        String desc,

-        String signature,

-        Label start,

-        Label end,

-        int index);

-

-    /**

-     * Visits a line number declaration.

-     * 

-     * @param line a line number. This number refers to the source file from

-     *        which the class was compiled.

-     * @param start the first instruction corresponding to this line number.

-     * @throws IllegalArgumentException if <tt>start</tt> has not already been

-     *         visited by this visitor (by the {@link #visitLabel visitLabel}

-     *         method).

-     */

-    void visitLineNumber(int line, Label start);

-

-    /**

-     * Visits the maximum stack size and the maximum number of local variables

-     * of the method.

-     * 

-     * @param maxStack maximum stack size of the method.

-     * @param maxLocals maximum number of local variables for the method.

-     */

-    void visitMaxs(int maxStack, int maxLocals);

-

-    /**

-     * Visits the end of the method. This method, which is the last one to be

-     * called, is used to inform the visitor that all the annotations and

-     * attributes of the method have been visited.

-     */

-    void visitEnd();

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/MethodWriter.java b/cglib-and-asm/src/org/mockito/asm/MethodWriter.java
deleted file mode 100644
index c920686..0000000
--- a/cglib-and-asm/src/org/mockito/asm/MethodWriter.java
+++ /dev/null
@@ -1,2601 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * A {@link MethodVisitor} that generates methods in bytecode form. Each visit

- * method of this class appends the bytecode corresponding to the visited

- * instruction to a byte vector, in the order these methods are called.

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-class MethodWriter implements MethodVisitor {

-

-    /**

-     * Pseudo access flag used to denote constructors.

-     */

-    static final int ACC_CONSTRUCTOR = 262144;

-

-    /**

-     * Frame has exactly the same locals as the previous stack map frame and

-     * number of stack items is zero.

-     */

-    static final int SAME_FRAME = 0; // to 63 (0-3f)

-

-    /**

-     * Frame has exactly the same locals as the previous stack map frame and

-     * number of stack items is 1

-     */

-    static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)

-

-    /**

-     * Reserved for future use

-     */

-    static final int RESERVED = 128;

-

-    /**

-     * Frame has exactly the same locals as the previous stack map frame and

-     * number of stack items is 1. Offset is bigger then 63;

-     */

-    static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7

-

-    /**

-     * Frame where current locals are the same as the locals in the previous

-     * frame, except that the k last locals are absent. The value of k is given

-     * by the formula 251-frame_type.

-     */

-    static final int CHOP_FRAME = 248; // to 250 (f8-fA)

-

-    /**

-     * Frame has exactly the same locals as the previous stack map frame and

-     * number of stack items is zero. Offset is bigger then 63;

-     */

-    static final int SAME_FRAME_EXTENDED = 251; // fb

-

-    /**

-     * Frame where current locals are the same as the locals in the previous

-     * frame, except that k additional locals are defined. The value of k is

-     * given by the formula frame_type-251.

-     */

-    static final int APPEND_FRAME = 252; // to 254 // fc-fe

-

-    /**

-     * Full frame

-     */

-    static final int FULL_FRAME = 255; // ff

-

-    /**

-     * Indicates that the stack map frames must be recomputed from scratch. In

-     * this case the maximum stack size and number of local variables is also

-     * recomputed from scratch.

-     * 

-     * @see #compute

-     */

-    private static final int FRAMES = 0;

-

-    /**

-     * Indicates that the maximum stack size and number of local variables must

-     * be automatically computed.

-     * 

-     * @see #compute

-     */

-    private static final int MAXS = 1;

-

-    /**

-     * Indicates that nothing must be automatically computed.

-     * 

-     * @see #compute

-     */

-    private static final int NOTHING = 2;

-

-    /**

-     * Next method writer (see {@link ClassWriter#firstMethod firstMethod}).

-     */

-    MethodWriter next;

-

-    /**

-     * The class writer to which this method must be added.

-     */

-    final ClassWriter cw;

-

-    /**

-     * Access flags of this method.

-     */

-    private int access;

-

-    /**

-     * The index of the constant pool item that contains the name of this

-     * method.

-     */

-    private final int name;

-

-    /**

-     * The index of the constant pool item that contains the descriptor of this

-     * method.

-     */

-    private final int desc;

-

-    /**

-     * The descriptor of this method.

-     */

-    private final String descriptor;

-

-    /**

-     * The signature of this method.

-     */

-    String signature;

-

-    /**

-     * If not zero, indicates that the code of this method must be copied from

-     * the ClassReader associated to this writer in <code>cw.cr</code>. More

-     * precisely, this field gives the index of the first byte to copied from

-     * <code>cw.cr.b</code>.

-     */

-    int classReaderOffset;

-

-    /**

-     * If not zero, indicates that the code of this method must be copied from

-     * the ClassReader associated to this writer in <code>cw.cr</code>. More

-     * precisely, this field gives the number of bytes to copied from

-     * <code>cw.cr.b</code>.

-     */

-    int classReaderLength;

-

-    /**

-     * Number of exceptions that can be thrown by this method.

-     */

-    int exceptionCount;

-

-    /**

-     * The exceptions that can be thrown by this method. More precisely, this

-     * array contains the indexes of the constant pool items that contain the

-     * internal names of these exception classes.

-     */

-    int[] exceptions;

-

-    /**

-     * The annotation default attribute of this method. May be <tt>null</tt>.

-     */

-    private ByteVector annd;

-

-    /**

-     * The runtime visible annotations of this method. May be <tt>null</tt>.

-     */

-    private AnnotationWriter anns;

-

-    /**

-     * The runtime invisible annotations of this method. May be <tt>null</tt>.

-     */

-    private AnnotationWriter ianns;

-

-    /**

-     * The runtime visible parameter annotations of this method. May be

-     * <tt>null</tt>.

-     */

-    private AnnotationWriter[] panns;

-

-    /**

-     * The runtime invisible parameter annotations of this method. May be

-     * <tt>null</tt>.

-     */

-    private AnnotationWriter[] ipanns;

-

-    /**

-     * The number of synthetic parameters of this method.

-     */

-    private int synthetics;

-

-    /**

-     * The non standard attributes of the method.

-     */

-    private Attribute attrs;

-

-    /**

-     * The bytecode of this method.

-     */

-    private ByteVector code = new ByteVector();

-

-    /**

-     * Maximum stack size of this method.

-     */

-    private int maxStack;

-

-    /**

-     * Maximum number of local variables for this method.

-     */

-    private int maxLocals;

-

-    /**

-     * Number of stack map frames in the StackMapTable attribute.

-     */

-    private int frameCount;

-

-    /**

-     * The StackMapTable attribute.

-     */

-    private ByteVector stackMap;

-

-    /**

-     * The offset of the last frame that was written in the StackMapTable

-     * attribute.

-     */

-    private int previousFrameOffset;

-

-    /**

-     * The last frame that was written in the StackMapTable attribute.

-     * 

-     * @see #frame

-     */

-    private int[] previousFrame;

-

-    /**

-     * Index of the next element to be added in {@link #frame}.

-     */

-    private int frameIndex;

-

-    /**

-     * The current stack map frame. The first element contains the offset of the

-     * instruction to which the frame corresponds, the second element is the

-     * number of locals and the third one is the number of stack elements. The

-     * local variables start at index 3 and are followed by the operand stack

-     * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =

-     * nStack, frame[3] = nLocal. All types are encoded as integers, with the

-     * same format as the one used in {@link Label}, but limited to BASE types.

-     */

-    private int[] frame;

-

-    /**

-     * Number of elements in the exception handler list.

-     */

-    private int handlerCount;

-

-    /**

-     * The first element in the exception handler list.

-     */

-    private Handler firstHandler;

-

-    /**

-     * The last element in the exception handler list.

-     */

-    private Handler lastHandler;

-

-    /**

-     * Number of entries in the LocalVariableTable attribute.

-     */

-    private int localVarCount;

-

-    /**

-     * The LocalVariableTable attribute.

-     */

-    private ByteVector localVar;

-

-    /**

-     * Number of entries in the LocalVariableTypeTable attribute.

-     */

-    private int localVarTypeCount;

-

-    /**

-     * The LocalVariableTypeTable attribute.

-     */

-    private ByteVector localVarType;

-

-    /**

-     * Number of entries in the LineNumberTable attribute.

-     */

-    private int lineNumberCount;

-

-    /**

-     * The LineNumberTable attribute.

-     */

-    private ByteVector lineNumber;

-

-    /**

-     * The non standard attributes of the method's code.

-     */

-    private Attribute cattrs;

-

-    /**

-     * Indicates if some jump instructions are too small and need to be resized.

-     */

-    private boolean resize;

-

-    /**

-     * The number of subroutines in this method.

-     */

-    private int subroutines;

-

-    // ------------------------------------------------------------------------

-

-    /*

-     * Fields for the control flow graph analysis algorithm (used to compute the

-     * maximum stack size). A control flow graph contains one node per "basic

-     * block", and one edge per "jump" from one basic block to another. Each

-     * node (i.e., each basic block) is represented by the Label object that

-     * corresponds to the first instruction of this basic block. Each node also

-     * stores the list of its successors in the graph, as a linked list of Edge

-     * objects.

-     */

-

-    /**

-     * Indicates what must be automatically computed.

-     * 

-     * @see #FRAMES

-     * @see #MAXS

-     * @see #NOTHING

-     */

-    private final int compute;

-

-    /**

-     * A list of labels. This list is the list of basic blocks in the method,

-     * i.e. a list of Label objects linked to each other by their

-     * {@link Label#successor} field, in the order they are visited by

-     * {@link MethodVisitor#visitLabel}, and starting with the first basic block.

-     */

-    private Label labels;

-

-    /**

-     * The previous basic block.

-     */

-    private Label previousBlock;

-

-    /**

-     * The current basic block.

-     */

-    private Label currentBlock;

-

-    /**

-     * The (relative) stack size after the last visited instruction. This size

-     * is relative to the beginning of the current basic block, i.e., the true

-     * stack size after the last visited instruction is equal to the

-     * {@link Label#inputStackTop beginStackSize} of the current basic block

-     * plus <tt>stackSize</tt>.

-     */

-    private int stackSize;

-

-    /**

-     * The (relative) maximum stack size after the last visited instruction.

-     * This size is relative to the beginning of the current basic block, i.e.,

-     * the true maximum stack size after the last visited instruction is equal

-     * to the {@link Label#inputStackTop beginStackSize} of the current basic

-     * block plus <tt>stackSize</tt>.

-     */

-    private int maxStackSize;

-

-    // ------------------------------------------------------------------------

-    // Constructor

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a new {@link MethodWriter}.

-     * 

-     * @param cw the class writer in which the method must be added.

-     * @param access the method's access flags (see {@link Opcodes}).

-     * @param name the method's name.

-     * @param desc the method's descriptor (see {@link Type}).

-     * @param signature the method's signature. May be <tt>null</tt>.

-     * @param exceptions the internal names of the method's exceptions. May be

-     *        <tt>null</tt>.

-     * @param computeMaxs <tt>true</tt> if the maximum stack size and number

-     *        of local variables must be automatically computed.

-     * @param computeFrames <tt>true</tt> if the stack map tables must be

-     *        recomputed from scratch.

-     */

-    MethodWriter(

-        final ClassWriter cw,

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions,

-        final boolean computeMaxs,

-        final boolean computeFrames)

-    {

-        if (cw.firstMethod == null) {

-            cw.firstMethod = this;

-        } else {

-            cw.lastMethod.next = this;

-        }

-        cw.lastMethod = this;

-        this.cw = cw;

-        this.access = access;

-        this.name = cw.newUTF8(name);

-        this.desc = cw.newUTF8(desc);

-        this.descriptor = desc;

-        if (ClassReader.SIGNATURES) {

-            this.signature = signature;

-        }

-        if (exceptions != null && exceptions.length > 0) {

-            exceptionCount = exceptions.length;

-            this.exceptions = new int[exceptionCount];

-            for (int i = 0; i < exceptionCount; ++i) {

-                this.exceptions[i] = cw.newClass(exceptions[i]);

-            }

-        }

-        this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);

-        if (computeMaxs || computeFrames) {

-            if (computeFrames && "<init>".equals(name)) {

-                this.access |= ACC_CONSTRUCTOR;

-            }

-            // updates maxLocals

-            int size = getArgumentsAndReturnSizes(descriptor) >> 2;

-            if ((access & Opcodes.ACC_STATIC) != 0) {

-                --size;

-            }

-            maxLocals = size;

-            // creates and visits the label for the first basic block

-            labels = new Label();

-            labels.status |= Label.PUSHED;

-            visitLabel(labels);

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the MethodVisitor interface

-    // ------------------------------------------------------------------------

-

-    public AnnotationVisitor visitAnnotationDefault() {

-        if (!ClassReader.ANNOTATIONS) {

-            return null;

-        }

-        annd = new ByteVector();

-        return new AnnotationWriter(cw, false, annd, null, 0);

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        if (!ClassReader.ANNOTATIONS) {

-            return null;

-        }

-        ByteVector bv = new ByteVector();

-        // write type, and reserve space for values count

-        bv.putShort(cw.newUTF8(desc)).putShort(0);

-        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);

-        if (visible) {

-            aw.next = anns;

-            anns = aw;

-        } else {

-            aw.next = ianns;

-            ianns = aw;

-        }

-        return aw;

-    }

-

-    public AnnotationVisitor visitParameterAnnotation(

-        final int parameter,

-        final String desc,

-        final boolean visible)

-    {

-        if (!ClassReader.ANNOTATIONS) {

-            return null;

-        }

-        ByteVector bv = new ByteVector();

-        if ("Ljava/lang/Synthetic;".equals(desc)) {

-            // workaround for a bug in javac with synthetic parameters

-            // see ClassReader.readParameterAnnotations

-            synthetics = Math.max(synthetics, parameter + 1);

-            return new AnnotationWriter(cw, false, bv, null, 0);

-        }

-        // write type, and reserve space for values count

-        bv.putShort(cw.newUTF8(desc)).putShort(0);

-        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);

-        if (visible) {

-            if (panns == null) {

-                panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];

-            }

-            aw.next = panns[parameter];

-            panns[parameter] = aw;

-        } else {

-            if (ipanns == null) {

-                ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];

-            }

-            aw.next = ipanns[parameter];

-            ipanns[parameter] = aw;

-        }

-        return aw;

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        if (attr.isCodeAttribute()) {

-            attr.next = cattrs;

-            cattrs = attr;

-        } else {

-            attr.next = attrs;

-            attrs = attr;

-        }

-    }

-

-    public void visitCode() {

-    }

-

-    public void visitFrame(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        if (!ClassReader.FRAMES || compute == FRAMES) {

-            return;

-        }

-

-        if (type == Opcodes.F_NEW) {

-            startFrame(code.length, nLocal, nStack);

-            for (int i = 0; i < nLocal; ++i) {

-                if (local[i] instanceof String) {

-                    frame[frameIndex++] = Frame.OBJECT

-                            | cw.addType((String) local[i]);

-                } else if (local[i] instanceof Integer) {

-                    frame[frameIndex++] = ((Integer) local[i]).intValue();

-                } else {

-                    frame[frameIndex++] = Frame.UNINITIALIZED

-                            | cw.addUninitializedType("",

-                                    ((Label) local[i]).position);

-                }

-            }

-            for (int i = 0; i < nStack; ++i) {

-                if (stack[i] instanceof String) {

-                    frame[frameIndex++] = Frame.OBJECT

-                            | cw.addType((String) stack[i]);

-                } else if (stack[i] instanceof Integer) {

-                    frame[frameIndex++] = ((Integer) stack[i]).intValue();

-                } else {

-                    frame[frameIndex++] = Frame.UNINITIALIZED

-                            | cw.addUninitializedType("",

-                                    ((Label) stack[i]).position);

-                }

-            }

-            endFrame();

-        } else {

-            int delta;

-            if (stackMap == null) {

-                stackMap = new ByteVector();

-                delta = code.length;

-            } else {

-                delta = code.length - previousFrameOffset - 1;

-            }

-

-            switch (type) {

-                case Opcodes.F_FULL:

-                    stackMap.putByte(FULL_FRAME)

-                            .putShort(delta)

-                            .putShort(nLocal);

-                    for (int i = 0; i < nLocal; ++i) {

-                        writeFrameType(local[i]);

-                    }

-                    stackMap.putShort(nStack);

-                    for (int i = 0; i < nStack; ++i) {

-                        writeFrameType(stack[i]);

-                    }

-                    break;

-                case Opcodes.F_APPEND:

-                    stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)

-                            .putShort(delta);

-                    for (int i = 0; i < nLocal; ++i) {

-                        writeFrameType(local[i]);

-                    }

-                    break;

-                case Opcodes.F_CHOP:

-                    stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)

-                            .putShort(delta);

-                    break;

-                case Opcodes.F_SAME:

-                    if (delta < 64) {

-                        stackMap.putByte(delta);

-                    } else {

-                        stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);

-                    }

-                    break;

-                case Opcodes.F_SAME1:

-                    if (delta < 64) {

-                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);

-                    } else {

-                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)

-                                .putShort(delta);

-                    }

-                    writeFrameType(stack[0]);

-                    break;

-            }

-

-            previousFrameOffset = code.length;

-            ++frameCount;

-        }

-    }

-

-    public void visitInsn(final int opcode) {

-        // adds the instruction to the bytecode of the method

-        code.putByte(opcode);

-        // update currentBlock

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, 0, null, null);

-            } else {

-                // updates current and max stack sizes

-                int size = stackSize + Frame.SIZE[opcode];

-                if (size > maxStackSize) {

-                    maxStackSize = size;

-                }

-                stackSize = size;

-            }

-            // if opcode == ATHROW or xRETURN, ends current block (no successor)

-            if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)

-                    || opcode == Opcodes.ATHROW)

-            {

-                noSuccessor();

-            }

-        }

-    }

-

-    public void visitIntInsn(final int opcode, final int operand) {

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, operand, null, null);

-            } else if (opcode != Opcodes.NEWARRAY) {

-                // updates current and max stack sizes only for NEWARRAY

-                // (stack size variation = 0 for BIPUSH or SIPUSH)

-                int size = stackSize + 1;

-                if (size > maxStackSize) {

-                    maxStackSize = size;

-                }

-                stackSize = size;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        if (opcode == Opcodes.SIPUSH) {

-            code.put12(opcode, operand);

-        } else { // BIPUSH or NEWARRAY

-            code.put11(opcode, operand);

-        }

-    }

-

-    public void visitVarInsn(final int opcode, final int var) {

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, var, null, null);

-            } else {

-                // updates current and max stack sizes

-                if (opcode == Opcodes.RET) {

-                    // no stack change, but end of current block (no successor)

-                    currentBlock.status |= Label.RET;

-                    // save 'stackSize' here for future use

-                    // (see {@link #findSubroutineSuccessors})

-                    currentBlock.inputStackTop = stackSize;

-                    noSuccessor();

-                } else { // xLOAD or xSTORE

-                    int size = stackSize + Frame.SIZE[opcode];

-                    if (size > maxStackSize) {

-                        maxStackSize = size;

-                    }

-                    stackSize = size;

-                }

-            }

-        }

-        if (compute != NOTHING) {

-            // updates max locals

-            int n;

-            if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD

-                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)

-            {

-                n = var + 2;

-            } else {

-                n = var + 1;

-            }

-            if (n > maxLocals) {

-                maxLocals = n;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        if (var < 4 && opcode != Opcodes.RET) {

-            int opt;

-            if (opcode < Opcodes.ISTORE) {

-                /* ILOAD_0 */

-                opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;

-            } else {

-                /* ISTORE_0 */

-                opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;

-            }

-            code.putByte(opt);

-        } else if (var >= 256) {

-            code.putByte(196 /* WIDE */).put12(opcode, var);

-        } else {

-            code.put11(opcode, var);

-        }

-        if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {

-            visitLabel(new Label());

-        }

-    }

-

-    public void visitTypeInsn(final int opcode, final String type) {

-        Item i = cw.newClassItem(type);

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, code.length, cw, i);

-            } else if (opcode == Opcodes.NEW) {

-                // updates current and max stack sizes only if opcode == NEW

-                // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)

-                int size = stackSize + 1;

-                if (size > maxStackSize) {

-                    maxStackSize = size;

-                }

-                stackSize = size;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        code.put12(opcode, i.index);

-    }

-

-    public void visitFieldInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        Item i = cw.newFieldItem(owner, name, desc);

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, 0, cw, i);

-            } else {

-                int size;

-                // computes the stack size variation

-                char c = desc.charAt(0);

-                switch (opcode) {

-                    case Opcodes.GETSTATIC:

-                        size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);

-                        break;

-                    case Opcodes.PUTSTATIC:

-                        size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);

-                        break;

-                    case Opcodes.GETFIELD:

-                        size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);

-                        break;

-                    // case Constants.PUTFIELD:

-                    default:

-                        size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);

-                        break;

-                }

-                // updates current and max stack sizes

-                if (size > maxStackSize) {

-                    maxStackSize = size;

-                }

-                stackSize = size;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        code.put12(opcode, i.index);

-    }

-

-    public void visitMethodInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        boolean itf = opcode == Opcodes.INVOKEINTERFACE;

-        Item i = cw.newMethodItem(owner, name, desc, itf);

-        int argSize = i.intVal;

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, 0, cw, i);

-            } else {

-                /*

-                 * computes the stack size variation. In order not to recompute

-                 * several times this variation for the same Item, we use the

-                 * intVal field of this item to store this variation, once it

-                 * has been computed. More precisely this intVal field stores

-                 * the sizes of the arguments and of the return value

-                 * corresponding to desc.

-                 */

-                if (argSize == 0) {

-                    // the above sizes have not been computed yet,

-                    // so we compute them...

-                    argSize = getArgumentsAndReturnSizes(desc);

-                    // ... and we save them in order

-                    // not to recompute them in the future

-                    i.intVal = argSize;

-                }

-                int size;

-                if (opcode == Opcodes.INVOKESTATIC) {

-                    size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;

-                } else {

-                    size = stackSize - (argSize >> 2) + (argSize & 0x03);

-                }

-                // updates current and max stack sizes

-                if (size > maxStackSize) {

-                    maxStackSize = size;

-                }

-                stackSize = size;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        if (itf) {

-            if (argSize == 0) {

-                argSize = getArgumentsAndReturnSizes(desc);

-                i.intVal = argSize;

-            }

-            code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);

-        } else {

-            code.put12(opcode, i.index);

-        }

-    }

-

-    public void visitJumpInsn(final int opcode, final Label label) {

-        Label nextInsn = null;

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(opcode, 0, null, null);

-                // 'label' is the target of a jump instruction

-                label.getFirst().status |= Label.TARGET;

-                // adds 'label' as a successor of this basic block

-                addSuccessor(Edge.NORMAL, label);

-                if (opcode != Opcodes.GOTO) {

-                    // creates a Label for the next basic block

-                    nextInsn = new Label();

-                }

-            } else {

-                if (opcode == Opcodes.JSR) {

-                    if ((label.status & Label.SUBROUTINE) == 0) {

-                        label.status |= Label.SUBROUTINE;

-                        ++subroutines;

-                    }

-                    currentBlock.status |= Label.JSR;

-                    addSuccessor(stackSize + 1, label);

-                    // creates a Label for the next basic block

-                    nextInsn = new Label();

-                    /*

-                     * note that, by construction in this method, a JSR block

-                     * has at least two successors in the control flow graph:

-                     * the first one leads the next instruction after the JSR,

-                     * while the second one leads to the JSR target.

-                     */

-                } else {

-                    // updates current stack size (max stack size unchanged

-                    // because stack size variation always negative in this

-                    // case)

-                    stackSize += Frame.SIZE[opcode];

-                    addSuccessor(stackSize, label);

-                }

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        if ((label.status & Label.RESOLVED) != 0

-                && label.position - code.length < Short.MIN_VALUE)

-        {

-            /*

-             * case of a backward jump with an offset < -32768. In this case we

-             * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx

-             * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the

-             * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>

-             * designates the instruction just after the GOTO_W.

-             */

-            if (opcode == Opcodes.GOTO) {

-                code.putByte(200); // GOTO_W

-            } else if (opcode == Opcodes.JSR) {

-                code.putByte(201); // JSR_W

-            } else {

-                // if the IF instruction is transformed into IFNOT GOTO_W the

-                // next instruction becomes the target of the IFNOT instruction

-                if (nextInsn != null) {

-                    nextInsn.status |= Label.TARGET;

-                }

-                code.putByte(opcode <= 166

-                        ? ((opcode + 1) ^ 1) - 1

-                        : opcode ^ 1);

-                code.putShort(8); // jump offset

-                code.putByte(200); // GOTO_W

-            }

-            label.put(this, code, code.length - 1, true);

-        } else {

-            /*

-             * case of a backward jump with an offset >= -32768, or of a forward

-             * jump with, of course, an unknown offset. In these cases we store

-             * the offset in 2 bytes (which will be increased in

-             * resizeInstructions, if needed).

-             */

-            code.putByte(opcode);

-            label.put(this, code, code.length - 1, false);

-        }

-        if (currentBlock != null) {

-            if (nextInsn != null) {

-                // if the jump instruction is not a GOTO, the next instruction

-                // is also a successor of this instruction. Calling visitLabel

-                // adds the label of this next instruction as a successor of the

-                // current block, and starts a new basic block

-                visitLabel(nextInsn);

-            }

-            if (opcode == Opcodes.GOTO) {

-                noSuccessor();

-            }

-        }

-    }

-

-    public void visitLabel(final Label label) {

-        // resolves previous forward references to label, if any

-        resize |= label.resolve(this, code.length, code.data);

-        // updates currentBlock

-        if ((label.status & Label.DEBUG) != 0) {

-            return;

-        }

-        if (compute == FRAMES) {

-            if (currentBlock != null) {

-                if (label.position == currentBlock.position) {

-                    // successive labels, do not start a new basic block

-                    currentBlock.status |= (label.status & Label.TARGET);

-                    label.frame = currentBlock.frame;

-                    return;

-                }

-                // ends current block (with one new successor)

-                addSuccessor(Edge.NORMAL, label);

-            }

-            // begins a new current block

-            currentBlock = label;

-            if (label.frame == null) {

-                label.frame = new Frame();

-                label.frame.owner = label;

-            }

-            // updates the basic block list

-            if (previousBlock != null) {

-                if (label.position == previousBlock.position) {

-                    previousBlock.status |= (label.status & Label.TARGET);

-                    label.frame = previousBlock.frame;

-                    currentBlock = previousBlock;

-                    return;

-                }

-                previousBlock.successor = label;

-            }

-            previousBlock = label;

-        } else if (compute == MAXS) {

-            if (currentBlock != null) {

-                // ends current block (with one new successor)

-                currentBlock.outputStackMax = maxStackSize;

-                addSuccessor(stackSize, label);

-            }

-            // begins a new current block

-            currentBlock = label;

-            // resets the relative current and max stack sizes

-            stackSize = 0;

-            maxStackSize = 0;

-            // updates the basic block list

-            if (previousBlock != null) {

-                previousBlock.successor = label;

-            }

-            previousBlock = label;

-        }

-    }

-

-    public void visitLdcInsn(final Object cst) {

-        Item i = cw.newConstItem(cst);

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);

-            } else {

-                int size;

-                // computes the stack size variation

-                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)

-                {

-                    size = stackSize + 2;

-                } else {

-                    size = stackSize + 1;

-                }

-                // updates current and max stack sizes

-                if (size > maxStackSize) {

-                    maxStackSize = size;

-                }

-                stackSize = size;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        int index = i.index;

-        if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {

-            code.put12(20 /* LDC2_W */, index);

-        } else if (index >= 256) {

-            code.put12(19 /* LDC_W */, index);

-        } else {

-            code.put11(Opcodes.LDC, index);

-        }

-    }

-

-    public void visitIincInsn(final int var, final int increment) {

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(Opcodes.IINC, var, null, null);

-            }

-        }

-        if (compute != NOTHING) {

-            // updates max locals

-            int n = var + 1;

-            if (n > maxLocals) {

-                maxLocals = n;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        if ((var > 255) || (increment > 127) || (increment < -128)) {

-            code.putByte(196 /* WIDE */)

-                    .put12(Opcodes.IINC, var)

-                    .putShort(increment);

-        } else {

-            code.putByte(Opcodes.IINC).put11(var, increment);

-        }

-    }

-

-    public void visitTableSwitchInsn(

-        final int min,

-        final int max,

-        final Label dflt,

-        final Label[] labels)

-    {

-        // adds the instruction to the bytecode of the method

-        int source = code.length;

-        code.putByte(Opcodes.TABLESWITCH);

-        code.length += (4 - code.length % 4) % 4;

-        dflt.put(this, code, source, true);

-        code.putInt(min).putInt(max);

-        for (int i = 0; i < labels.length; ++i) {

-            labels[i].put(this, code, source, true);

-        }

-        // updates currentBlock

-        visitSwitchInsn(dflt, labels);

-    }

-

-    public void visitLookupSwitchInsn(

-        final Label dflt,

-        final int[] keys,

-        final Label[] labels)

-    {

-        // adds the instruction to the bytecode of the method

-        int source = code.length;

-        code.putByte(Opcodes.LOOKUPSWITCH);

-        code.length += (4 - code.length % 4) % 4;

-        dflt.put(this, code, source, true);

-        code.putInt(labels.length);

-        for (int i = 0; i < labels.length; ++i) {

-            code.putInt(keys[i]);

-            labels[i].put(this, code, source, true);

-        }

-        // updates currentBlock

-        visitSwitchInsn(dflt, labels);

-    }

-

-    private void visitSwitchInsn(final Label dflt, final Label[] labels) {

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);

-                // adds current block successors

-                addSuccessor(Edge.NORMAL, dflt);

-                dflt.getFirst().status |= Label.TARGET;

-                for (int i = 0; i < labels.length; ++i) {

-                    addSuccessor(Edge.NORMAL, labels[i]);

-                    labels[i].getFirst().status |= Label.TARGET;

-                }

-            } else {

-                // updates current stack size (max stack size unchanged)

-                --stackSize;

-                // adds current block successors

-                addSuccessor(stackSize, dflt);

-                for (int i = 0; i < labels.length; ++i) {

-                    addSuccessor(stackSize, labels[i]);

-                }

-            }

-            // ends current block

-            noSuccessor();

-        }

-    }

-

-    public void visitMultiANewArrayInsn(final String desc, final int dims) {

-        Item i = cw.newClassItem(desc);

-        // Label currentBlock = this.currentBlock;

-        if (currentBlock != null) {

-            if (compute == FRAMES) {

-                currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);

-            } else {

-                // updates current stack size (max stack size unchanged because

-                // stack size variation always negative or null)

-                stackSize += 1 - dims;

-            }

-        }

-        // adds the instruction to the bytecode of the method

-        code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);

-    }

-

-    public void visitTryCatchBlock(

-        final Label start,

-        final Label end,

-        final Label handler,

-        final String type)

-    {

-        ++handlerCount;

-        Handler h = new Handler();

-        h.start = start;

-        h.end = end;

-        h.handler = handler;

-        h.desc = type;

-        h.type = type != null ? cw.newClass(type) : 0;

-        if (lastHandler == null) {

-            firstHandler = h;

-        } else {

-            lastHandler.next = h;

-        }

-        lastHandler = h;

-    }

-

-    public void visitLocalVariable(

-        final String name,

-        final String desc,

-        final String signature,

-        final Label start,

-        final Label end,

-        final int index)

-    {

-        if (signature != null) {

-            if (localVarType == null) {

-                localVarType = new ByteVector();

-            }

-            ++localVarTypeCount;

-            localVarType.putShort(start.position)

-                    .putShort(end.position - start.position)

-                    .putShort(cw.newUTF8(name))

-                    .putShort(cw.newUTF8(signature))

-                    .putShort(index);

-        }

-        if (localVar == null) {

-            localVar = new ByteVector();

-        }

-        ++localVarCount;

-        localVar.putShort(start.position)

-                .putShort(end.position - start.position)

-                .putShort(cw.newUTF8(name))

-                .putShort(cw.newUTF8(desc))

-                .putShort(index);

-        if (compute != NOTHING) {

-            // updates max locals

-            char c = desc.charAt(0);

-            int n = index + (c == 'J' || c == 'D' ? 2 : 1);

-            if (n > maxLocals) {

-                maxLocals = n;

-            }

-        }

-    }

-

-    public void visitLineNumber(final int line, final Label start) {

-        if (lineNumber == null) {

-            lineNumber = new ByteVector();

-        }

-        ++lineNumberCount;

-        lineNumber.putShort(start.position);

-        lineNumber.putShort(line);

-    }

-

-    public void visitMaxs(final int maxStack, final int maxLocals) {

-        if (ClassReader.FRAMES && compute == FRAMES) {

-            // completes the control flow graph with exception handler blocks

-            Handler handler = firstHandler;

-            while (handler != null) {

-                Label l = handler.start.getFirst();

-                Label h = handler.handler.getFirst();

-                Label e = handler.end.getFirst();

-                // computes the kind of the edges to 'h'

-                String t = handler.desc == null

-                        ? "java/lang/Throwable"

-                        : handler.desc;

-                int kind = Frame.OBJECT | cw.addType(t);

-                // h is an exception handler

-                h.status |= Label.TARGET;

-                // adds 'h' as a successor of labels between 'start' and 'end'

-                while (l != e) {

-                    // creates an edge to 'h'

-                    Edge b = new Edge();

-                    b.info = kind;

-                    b.successor = h;

-                    // adds it to the successors of 'l'

-                    b.next = l.successors;

-                    l.successors = b;

-                    // goes to the next label

-                    l = l.successor;

-                }

-                handler = handler.next;

-            }

-

-            // creates and visits the first (implicit) frame

-            Frame f = labels.frame;

-            Type[] args = Type.getArgumentTypes(descriptor);

-            f.initInputFrame(cw, access, args, this.maxLocals);

-            visitFrame(f);

-

-            /*

-             * fix point algorithm: mark the first basic block as 'changed'

-             * (i.e. put it in the 'changed' list) and, while there are changed

-             * basic blocks, choose one, mark it as unchanged, and update its

-             * successors (which can be changed in the process).

-             */

-            int max = 0;

-            Label changed = labels;

-            while (changed != null) {

-                // removes a basic block from the list of changed basic blocks

-                Label l = changed;

-                changed = changed.next;

-                l.next = null;

-                f = l.frame;

-                // a reacheable jump target must be stored in the stack map

-                if ((l.status & Label.TARGET) != 0) {

-                    l.status |= Label.STORE;

-                }

-                // all visited labels are reacheable, by definition

-                l.status |= Label.REACHABLE;

-                // updates the (absolute) maximum stack size

-                int blockMax = f.inputStack.length + l.outputStackMax;

-                if (blockMax > max) {

-                    max = blockMax;

-                }

-                // updates the successors of the current basic block

-                Edge e = l.successors;

-                while (e != null) {

-                    Label n = e.successor.getFirst();

-                    boolean change = f.merge(cw, n.frame, e.info);

-                    if (change && n.next == null) {

-                        // if n has changed and is not already in the 'changed'

-                        // list, adds it to this list

-                        n.next = changed;

-                        changed = n;

-                    }

-                    e = e.next;

-                }

-            }

-            this.maxStack = max;

-

-            // visits all the frames that must be stored in the stack map

-            Label l = labels;

-            while (l != null) {

-                f = l.frame;

-                if ((l.status & Label.STORE) != 0) {

-                    visitFrame(f);

-                }

-                if ((l.status & Label.REACHABLE) == 0) {

-                    // finds start and end of dead basic block

-                    Label k = l.successor;

-                    int start = l.position;

-                    int end = (k == null ? code.length : k.position) - 1;

-                    // if non empty basic block

-                    if (end >= start) {

-                        // replaces instructions with NOP ... NOP ATHROW

-                        for (int i = start; i < end; ++i) {

-                            code.data[i] = Opcodes.NOP;

-                        }

-                        code.data[end] = (byte) Opcodes.ATHROW;

-                        // emits a frame for this unreachable block

-                        startFrame(start, 0, 1);

-                        frame[frameIndex++] = Frame.OBJECT

-                                | cw.addType("java/lang/Throwable");

-                        endFrame();

-                    }

-                }

-                l = l.successor;

-            }

-        } else if (compute == MAXS) {

-            // completes the control flow graph with exception handler blocks

-            Handler handler = firstHandler;

-            while (handler != null) {

-                Label l = handler.start;

-                Label h = handler.handler;

-                Label e = handler.end;

-                // adds 'h' as a successor of labels between 'start' and 'end'

-                while (l != e) {

-                    // creates an edge to 'h'

-                    Edge b = new Edge();

-                    b.info = Edge.EXCEPTION;

-                    b.successor = h;

-                    // adds it to the successors of 'l'

-                    if ((l.status & Label.JSR) == 0) {

-                        b.next = l.successors;

-                        l.successors = b;

-                    } else {

-                        // if l is a JSR block, adds b after the first two edges

-                        // to preserve the hypothesis about JSR block successors

-                        // order (see {@link #visitJumpInsn})

-                        b.next = l.successors.next.next;

-                        l.successors.next.next = b;

-                    }

-                    // goes to the next label

-                    l = l.successor;

-                }

-                handler = handler.next;

-            }

-

-            if (subroutines > 0) {

-                // completes the control flow graph with the RET successors

-                /*

-                 * first step: finds the subroutines. This step determines, for

-                 * each basic block, to which subroutine(s) it belongs.

-                 */

-                // finds the basic blocks that belong to the "main" subroutine

-                int id = 0;

-                labels.visitSubroutine(null, 1, subroutines);

-                // finds the basic blocks that belong to the real subroutines

-                Label l = labels;

-                while (l != null) {

-                    if ((l.status & Label.JSR) != 0) {

-                        // the subroutine is defined by l's TARGET, not by l

-                        Label subroutine = l.successors.next.successor;

-                        // if this subroutine has not been visited yet...

-                        if ((subroutine.status & Label.VISITED) == 0) {

-                            // ...assigns it a new id and finds its basic blocks

-                            id += 1;

-                            subroutine.visitSubroutine(null, (id / 32L) << 32

-                                    | (1L << (id % 32)), subroutines);

-                        }

-                    }

-                    l = l.successor;

-                }

-                // second step: finds the successors of RET blocks

-                l = labels;

-                while (l != null) {

-                    if ((l.status & Label.JSR) != 0) {

-                        Label L = labels;

-                        while (L != null) {

-                            L.status &= ~Label.VISITED;

-                            L = L.successor;

-                        }

-                        // the subroutine is defined by l's TARGET, not by l

-                        Label subroutine = l.successors.next.successor;

-                        subroutine.visitSubroutine(l, 0, subroutines);

-                    }

-                    l = l.successor;

-                }

-            }

-

-            /*

-             * control flow analysis algorithm: while the block stack is not

-             * empty, pop a block from this stack, update the max stack size,

-             * compute the true (non relative) begin stack size of the

-             * successors of this block, and push these successors onto the

-             * stack (unless they have already been pushed onto the stack).

-             * Note: by hypothesis, the {@link Label#inputStackTop} of the

-             * blocks in the block stack are the true (non relative) beginning

-             * stack sizes of these blocks.

-             */

-            int max = 0;

-            Label stack = labels;

-            while (stack != null) {

-                // pops a block from the stack

-                Label l = stack;

-                stack = stack.next;

-                // computes the true (non relative) max stack size of this block

-                int start = l.inputStackTop;

-                int blockMax = start + l.outputStackMax;

-                // updates the global max stack size

-                if (blockMax > max) {

-                    max = blockMax;

-                }

-                // analyzes the successors of the block

-                Edge b = l.successors;

-                if ((l.status & Label.JSR) != 0) {

-                    // ignores the first edge of JSR blocks (virtual successor)

-                    b = b.next;

-                }

-                while (b != null) {

-                    l = b.successor;

-                    // if this successor has not already been pushed...

-                    if ((l.status & Label.PUSHED) == 0) {

-                        // computes its true beginning stack size...

-                        l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start

-                                + b.info;

-                        // ...and pushes it onto the stack

-                        l.status |= Label.PUSHED;

-                        l.next = stack;

-                        stack = l;

-                    }

-                    b = b.next;

-                }

-            }

-            this.maxStack = max;

-        } else {

-            this.maxStack = maxStack;

-            this.maxLocals = maxLocals;

-        }

-    }

-

-    public void visitEnd() {

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods: control flow analysis algorithm

-    // ------------------------------------------------------------------------

-

-    /**

-     * Computes the size of the arguments and of the return value of a method.

-     * 

-     * @param desc the descriptor of a method.

-     * @return the size of the arguments of the method (plus one for the

-     *         implicit this argument), argSize, and the size of its return

-     *         value, retSize, packed into a single int i =

-     *         <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal

-     *         to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).

-     */

-    static int getArgumentsAndReturnSizes(final String desc) {

-        int n = 1;

-        int c = 1;

-        while (true) {

-            char car = desc.charAt(c++);

-            if (car == ')') {

-                car = desc.charAt(c);

-                return n << 2

-                        | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));

-            } else if (car == 'L') {

-                while (desc.charAt(c++) != ';') {

-                }

-                n += 1;

-            } else if (car == '[') {

-                while ((car = desc.charAt(c)) == '[') {

-                    ++c;

-                }

-                if (car == 'D' || car == 'J') {

-                    n -= 1;

-                }

-            } else if (car == 'D' || car == 'J') {

-                n += 2;

-            } else {

-                n += 1;

-            }

-        }

-    }

-

-    /**

-     * Adds a successor to the {@link #currentBlock currentBlock} block.

-     * 

-     * @param info information about the control flow edge to be added.

-     * @param successor the successor block to be added to the current block.

-     */

-    private void addSuccessor(final int info, final Label successor) {

-        // creates and initializes an Edge object...

-        Edge b = new Edge();

-        b.info = info;

-        b.successor = successor;

-        // ...and adds it to the successor list of the currentBlock block

-        b.next = currentBlock.successors;

-        currentBlock.successors = b;

-    }

-

-    /**

-     * Ends the current basic block. This method must be used in the case where

-     * the current basic block does not have any successor.

-     */

-    private void noSuccessor() {

-        if (compute == FRAMES) {

-            Label l = new Label();

-            l.frame = new Frame();

-            l.frame.owner = l;

-            l.resolve(this, code.length, code.data);

-            previousBlock.successor = l;

-            previousBlock = l;

-        } else {

-            currentBlock.outputStackMax = maxStackSize;

-        }

-        currentBlock = null;

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods: stack map frames

-    // ------------------------------------------------------------------------

-

-    /**

-     * Visits a frame that has been computed from scratch.

-     * 

-     * @param f the frame that must be visited.

-     */

-    private void visitFrame(final Frame f) {

-        int i, t;

-        int nTop = 0;

-        int nLocal = 0;

-        int nStack = 0;

-        int[] locals = f.inputLocals;

-        int[] stacks = f.inputStack;

-        // computes the number of locals (ignores TOP types that are just after

-        // a LONG or a DOUBLE, and all trailing TOP types)

-        for (i = 0; i < locals.length; ++i) {

-            t = locals[i];

-            if (t == Frame.TOP) {

-                ++nTop;

-            } else {

-                nLocal += nTop + 1;

-                nTop = 0;

-            }

-            if (t == Frame.LONG || t == Frame.DOUBLE) {

-                ++i;

-            }

-        }

-        // computes the stack size (ignores TOP types that are just after

-        // a LONG or a DOUBLE)

-        for (i = 0; i < stacks.length; ++i) {

-            t = stacks[i];

-            ++nStack;

-            if (t == Frame.LONG || t == Frame.DOUBLE) {

-                ++i;

-            }

-        }

-        // visits the frame and its content

-        startFrame(f.owner.position, nLocal, nStack);

-        for (i = 0; nLocal > 0; ++i, --nLocal) {

-            t = locals[i];

-            frame[frameIndex++] = t;

-            if (t == Frame.LONG || t == Frame.DOUBLE) {

-                ++i;

-            }

-        }

-        for (i = 0; i < stacks.length; ++i) {

-            t = stacks[i];

-            frame[frameIndex++] = t;

-            if (t == Frame.LONG || t == Frame.DOUBLE) {

-                ++i;

-            }

-        }

-        endFrame();

-    }

-

-    /**

-     * Starts the visit of a stack map frame.

-     * 

-     * @param offset the offset of the instruction to which the frame

-     *        corresponds.

-     * @param nLocal the number of local variables in the frame.

-     * @param nStack the number of stack elements in the frame.

-     */

-    private void startFrame(final int offset, final int nLocal, final int nStack)

-    {

-        int n = 3 + nLocal + nStack;

-        if (frame == null || frame.length < n) {

-            frame = new int[n];

-        }

-        frame[0] = offset;

-        frame[1] = nLocal;

-        frame[2] = nStack;

-        frameIndex = 3;

-    }

-

-    /**

-     * Checks if the visit of the current frame {@link #frame} is finished, and

-     * if yes, write it in the StackMapTable attribute.

-     */

-    private void endFrame() {

-        if (previousFrame != null) { // do not write the first frame

-            if (stackMap == null) {

-                stackMap = new ByteVector();

-            }

-            writeFrame();

-            ++frameCount;

-        }

-        previousFrame = frame;

-        frame = null;

-    }

-

-    /**

-     * Compress and writes the current frame {@link #frame} in the StackMapTable

-     * attribute.

-     */

-    private void writeFrame() {

-        int clocalsSize = frame[1];

-        int cstackSize = frame[2];

-        if ((cw.version & 0xFFFF) < Opcodes.V1_6) {

-            stackMap.putShort(frame[0]).putShort(clocalsSize);

-            writeFrameTypes(3, 3 + clocalsSize);

-            stackMap.putShort(cstackSize);

-            writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);

-            return;

-        }

-        int localsSize = previousFrame[1];

-        int type = FULL_FRAME;

-        int k = 0;

-        int delta;

-        if (frameCount == 0) {

-            delta = frame[0];

-        } else {

-            delta = frame[0] - previousFrame[0] - 1;

-        }

-        if (cstackSize == 0) {

-            k = clocalsSize - localsSize;

-            switch (k) {

-                case -3:

-                case -2:

-                case -1:

-                    type = CHOP_FRAME;

-                    localsSize = clocalsSize;

-                    break;

-                case 0:

-                    type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;

-                    break;

-                case 1:

-                case 2:

-                case 3:

-                    type = APPEND_FRAME;

-                    break;

-            }

-        } else if (clocalsSize == localsSize && cstackSize == 1) {

-            type = delta < 63

-                    ? SAME_LOCALS_1_STACK_ITEM_FRAME

-                    : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;

-        }

-        if (type != FULL_FRAME) {

-            // verify if locals are the same

-            int l = 3;

-            for (int j = 0; j < localsSize; j++) {

-                if (frame[l] != previousFrame[l]) {

-                    type = FULL_FRAME;

-                    break;

-                }

-                l++;

-            }

-        }

-        switch (type) {

-            case SAME_FRAME:

-                stackMap.putByte(delta);

-                break;

-            case SAME_LOCALS_1_STACK_ITEM_FRAME:

-                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);

-                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);

-                break;

-            case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:

-                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)

-                        .putShort(delta);

-                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);

-                break;

-            case SAME_FRAME_EXTENDED:

-                stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);

-                break;

-            case CHOP_FRAME:

-                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);

-                break;

-            case APPEND_FRAME:

-                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);

-                writeFrameTypes(3 + localsSize, 3 + clocalsSize);

-                break;

-            // case FULL_FRAME:

-            default:

-                stackMap.putByte(FULL_FRAME)

-                        .putShort(delta)

-                        .putShort(clocalsSize);

-                writeFrameTypes(3, 3 + clocalsSize);

-                stackMap.putShort(cstackSize);

-                writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);

-        }

-    }

-

-    /**

-     * Writes some types of the current frame {@link #frame} into the

-     * StackMapTableAttribute. This method converts types from the format used

-     * in {@link Label} to the format used in StackMapTable attributes. In

-     * particular, it converts type table indexes to constant pool indexes.

-     * 

-     * @param start index of the first type in {@link #frame} to write.

-     * @param end index of last type in {@link #frame} to write (exclusive).

-     */

-    private void writeFrameTypes(final int start, final int end) {

-        for (int i = start; i < end; ++i) {

-            int t = frame[i];

-            int d = t & Frame.DIM;

-            if (d == 0) {

-                int v = t & Frame.BASE_VALUE;

-                switch (t & Frame.BASE_KIND) {

-                    case Frame.OBJECT:

-                        stackMap.putByte(7)

-                                .putShort(cw.newClass(cw.typeTable[v].strVal1));

-                        break;

-                    case Frame.UNINITIALIZED:

-                        stackMap.putByte(8).putShort(cw.typeTable[v].intVal);

-                        break;

-                    default:

-                        stackMap.putByte(v);

-                }

-            } else {

-                StringBuffer buf = new StringBuffer();

-                d >>= 28;

-                while (d-- > 0) {

-                    buf.append('[');

-                }

-                if ((t & Frame.BASE_KIND) == Frame.OBJECT) {

-                    buf.append('L');

-                    buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);

-                    buf.append(';');

-                } else {

-                    switch (t & 0xF) {

-                        case 1:

-                            buf.append('I');

-                            break;

-                        case 2:

-                            buf.append('F');

-                            break;

-                        case 3:

-                            buf.append('D');

-                            break;

-                        case 9:

-                            buf.append('Z');

-                            break;

-                        case 10:

-                            buf.append('B');

-                            break;

-                        case 11:

-                            buf.append('C');

-                            break;

-                        case 12:

-                            buf.append('S');

-                            break;

-                        default:

-                            buf.append('J');

-                    }

-                }

-                stackMap.putByte(7).putShort(cw.newClass(buf.toString()));

-            }

-        }

-    }

-

-    private void writeFrameType(final Object type) {

-        if (type instanceof String) {

-            stackMap.putByte(7).putShort(cw.newClass((String) type));

-        } else if (type instanceof Integer) {

-            stackMap.putByte(((Integer) type).intValue());

-        } else {

-            stackMap.putByte(8).putShort(((Label) type).position);

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods: dump bytecode array

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the size of the bytecode of this method.

-     * 

-     * @return the size of the bytecode of this method.

-     */

-    final int getSize() {

-        if (classReaderOffset != 0) {

-            return 6 + classReaderLength;

-        }

-        if (resize) {

-            // replaces the temporary jump opcodes introduced by Label.resolve.

-            if (ClassReader.RESIZE) {

-                resizeInstructions();

-            } else {

-                throw new RuntimeException("Method code too large!");

-            }

-        }

-        int size = 8;

-        if (code.length > 0) {

-            cw.newUTF8("Code");

-            size += 18 + code.length + 8 * handlerCount;

-            if (localVar != null) {

-                cw.newUTF8("LocalVariableTable");

-                size += 8 + localVar.length;

-            }

-            if (localVarType != null) {

-                cw.newUTF8("LocalVariableTypeTable");

-                size += 8 + localVarType.length;

-            }

-            if (lineNumber != null) {

-                cw.newUTF8("LineNumberTable");

-                size += 8 + lineNumber.length;

-            }

-            if (stackMap != null) {

-                boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;

-                cw.newUTF8(zip ? "StackMapTable" : "StackMap");

-                size += 8 + stackMap.length;

-            }

-            if (cattrs != null) {

-                size += cattrs.getSize(cw,

-                        code.data,

-                        code.length,

-                        maxStack,

-                        maxLocals);

-            }

-        }

-        if (exceptionCount > 0) {

-            cw.newUTF8("Exceptions");

-            size += 8 + 2 * exceptionCount;

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (cw.version & 0xffff) < Opcodes.V1_5)

-        {

-            cw.newUTF8("Synthetic");

-            size += 6;

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            cw.newUTF8("Deprecated");

-            size += 6;

-        }

-        if (ClassReader.SIGNATURES && signature != null) {

-            cw.newUTF8("Signature");

-            cw.newUTF8(signature);

-            size += 8;

-        }

-        if (ClassReader.ANNOTATIONS && annd != null) {

-            cw.newUTF8("AnnotationDefault");

-            size += 6 + annd.length;

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            cw.newUTF8("RuntimeVisibleAnnotations");

-            size += 8 + anns.getSize();

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            cw.newUTF8("RuntimeInvisibleAnnotations");

-            size += 8 + ianns.getSize();

-        }

-        if (ClassReader.ANNOTATIONS && panns != null) {

-            cw.newUTF8("RuntimeVisibleParameterAnnotations");

-            size += 7 + 2 * (panns.length - synthetics);

-            for (int i = panns.length - 1; i >= synthetics; --i) {

-                size += panns[i] == null ? 0 : panns[i].getSize();

-            }

-        }

-        if (ClassReader.ANNOTATIONS && ipanns != null) {

-            cw.newUTF8("RuntimeInvisibleParameterAnnotations");

-            size += 7 + 2 * (ipanns.length - synthetics);

-            for (int i = ipanns.length - 1; i >= synthetics; --i) {

-                size += ipanns[i] == null ? 0 : ipanns[i].getSize();

-            }

-        }

-        if (attrs != null) {

-            size += attrs.getSize(cw, null, 0, -1, -1);

-        }

-        return size;

-    }

-

-    /**

-     * Puts the bytecode of this method in the given byte vector.

-     * 

-     * @param out the byte vector into which the bytecode of this method must be

-     *        copied.

-     */

-    final void put(final ByteVector out) {

-        out.putShort(access).putShort(name).putShort(desc);

-        if (classReaderOffset != 0) {

-            out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);

-            return;

-        }

-        int attributeCount = 0;

-        if (code.length > 0) {

-            ++attributeCount;

-        }

-        if (exceptionCount > 0) {

-            ++attributeCount;

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (cw.version & 0xffff) < Opcodes.V1_5)

-        {

-            ++attributeCount;

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            ++attributeCount;

-        }

-        if (ClassReader.SIGNATURES && signature != null) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && annd != null) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && panns != null) {

-            ++attributeCount;

-        }

-        if (ClassReader.ANNOTATIONS && ipanns != null) {

-            ++attributeCount;

-        }

-        if (attrs != null) {

-            attributeCount += attrs.getCount();

-        }

-        out.putShort(attributeCount);

-        if (code.length > 0) {

-            int size = 12 + code.length + 8 * handlerCount;

-            if (localVar != null) {

-                size += 8 + localVar.length;

-            }

-            if (localVarType != null) {

-                size += 8 + localVarType.length;

-            }

-            if (lineNumber != null) {

-                size += 8 + lineNumber.length;

-            }

-            if (stackMap != null) {

-                size += 8 + stackMap.length;

-            }

-            if (cattrs != null) {

-                size += cattrs.getSize(cw,

-                        code.data,

-                        code.length,

-                        maxStack,

-                        maxLocals);

-            }

-            out.putShort(cw.newUTF8("Code")).putInt(size);

-            out.putShort(maxStack).putShort(maxLocals);

-            out.putInt(code.length).putByteArray(code.data, 0, code.length);

-            out.putShort(handlerCount);

-            if (handlerCount > 0) {

-                Handler h = firstHandler;

-                while (h != null) {

-                    out.putShort(h.start.position)

-                            .putShort(h.end.position)

-                            .putShort(h.handler.position)

-                            .putShort(h.type);

-                    h = h.next;

-                }

-            }

-            attributeCount = 0;

-            if (localVar != null) {

-                ++attributeCount;

-            }

-            if (localVarType != null) {

-                ++attributeCount;

-            }

-            if (lineNumber != null) {

-                ++attributeCount;

-            }

-            if (stackMap != null) {

-                ++attributeCount;

-            }

-            if (cattrs != null) {

-                attributeCount += cattrs.getCount();

-            }

-            out.putShort(attributeCount);

-            if (localVar != null) {

-                out.putShort(cw.newUTF8("LocalVariableTable"));

-                out.putInt(localVar.length + 2).putShort(localVarCount);

-                out.putByteArray(localVar.data, 0, localVar.length);

-            }

-            if (localVarType != null) {

-                out.putShort(cw.newUTF8("LocalVariableTypeTable"));

-                out.putInt(localVarType.length + 2).putShort(localVarTypeCount);

-                out.putByteArray(localVarType.data, 0, localVarType.length);

-            }

-            if (lineNumber != null) {

-                out.putShort(cw.newUTF8("LineNumberTable"));

-                out.putInt(lineNumber.length + 2).putShort(lineNumberCount);

-                out.putByteArray(lineNumber.data, 0, lineNumber.length);

-            }

-            if (stackMap != null) {

-                boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;

-                out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap"));

-                out.putInt(stackMap.length + 2).putShort(frameCount);

-                out.putByteArray(stackMap.data, 0, stackMap.length);

-            }

-            if (cattrs != null) {

-                cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);

-            }

-        }

-        if (exceptionCount > 0) {

-            out.putShort(cw.newUTF8("Exceptions"))

-                    .putInt(2 * exceptionCount + 2);

-            out.putShort(exceptionCount);

-            for (int i = 0; i < exceptionCount; ++i) {

-                out.putShort(exceptions[i]);

-            }

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0

-                && (cw.version & 0xffff) < Opcodes.V1_5)

-        {

-            out.putShort(cw.newUTF8("Synthetic")).putInt(0);

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            out.putShort(cw.newUTF8("Deprecated")).putInt(0);

-        }

-        if (ClassReader.SIGNATURES && signature != null) {

-            out.putShort(cw.newUTF8("Signature"))

-                    .putInt(2)

-                    .putShort(cw.newUTF8(signature));

-        }

-        if (ClassReader.ANNOTATIONS && annd != null) {

-            out.putShort(cw.newUTF8("AnnotationDefault"));

-            out.putInt(annd.length);

-            out.putByteArray(annd.data, 0, annd.length);

-        }

-        if (ClassReader.ANNOTATIONS && anns != null) {

-            out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));

-            anns.put(out);

-        }

-        if (ClassReader.ANNOTATIONS && ianns != null) {

-            out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));

-            ianns.put(out);

-        }

-        if (ClassReader.ANNOTATIONS && panns != null) {

-            out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));

-            AnnotationWriter.put(panns, synthetics, out);

-        }

-        if (ClassReader.ANNOTATIONS && ipanns != null) {

-            out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));

-            AnnotationWriter.put(ipanns, synthetics, out);

-        }

-        if (attrs != null) {

-            attrs.put(cw, null, 0, -1, -1, out);

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)

-    // ------------------------------------------------------------------------

-

-    /**

-     * Resizes and replaces the temporary instructions inserted by

-     * {@link Label#resolve} for wide forward jumps, while keeping jump offsets

-     * and instruction addresses consistent. This may require to resize other

-     * existing instructions, or even to introduce new instructions: for

-     * example, increasing the size of an instruction by 2 at the middle of a

-     * method can increases the offset of an IFEQ instruction from 32766 to

-     * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W

-     * 32765. This, in turn, may require to increase the size of another jump

-     * instruction, and so on... All these operations are handled automatically

-     * by this method. <p> <i>This method must be called after all the method

-     * that is being built has been visited</i>. In particular, the

-     * {@link Label Label} objects used to construct the method are no longer

-     * valid after this method has been called.

-     */

-    private void resizeInstructions() {

-        byte[] b = code.data; // bytecode of the method

-        int u, v, label; // indexes in b

-        int i, j; // loop indexes

-        /*

-         * 1st step: As explained above, resizing an instruction may require to

-         * resize another one, which may require to resize yet another one, and

-         * so on. The first step of the algorithm consists in finding all the

-         * instructions that need to be resized, without modifying the code.

-         * This is done by the following "fix point" algorithm:

-         * 

-         * Parse the code to find the jump instructions whose offset will need

-         * more than 2 bytes to be stored (the future offset is computed from

-         * the current offset and from the number of bytes that will be inserted

-         * or removed between the source and target instructions). For each such

-         * instruction, adds an entry in (a copy of) the indexes and sizes

-         * arrays (if this has not already been done in a previous iteration!).

-         * 

-         * If at least one entry has been added during the previous step, go

-         * back to the beginning, otherwise stop.

-         * 

-         * In fact the real algorithm is complicated by the fact that the size

-         * of TABLESWITCH and LOOKUPSWITCH instructions depends on their

-         * position in the bytecode (because of padding). In order to ensure the

-         * convergence of the algorithm, the number of bytes to be added or

-         * removed from these instructions is over estimated during the previous

-         * loop, and computed exactly only after the loop is finished (this

-         * requires another pass to parse the bytecode of the method).

-         */

-        int[] allIndexes = new int[0]; // copy of indexes

-        int[] allSizes = new int[0]; // copy of sizes

-        boolean[] resize; // instructions to be resized

-        int newOffset; // future offset of a jump instruction

-

-        resize = new boolean[code.length];

-

-        // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done

-        int state = 3;

-        do {

-            if (state == 3) {

-                state = 2;

-            }

-            u = 0;

-            while (u < b.length) {

-                int opcode = b[u] & 0xFF; // opcode of current instruction

-                int insert = 0; // bytes to be added after this instruction

-

-                switch (ClassWriter.TYPE[opcode]) {

-                    case ClassWriter.NOARG_INSN:

-                    case ClassWriter.IMPLVAR_INSN:

-                        u += 1;

-                        break;

-                    case ClassWriter.LABEL_INSN:

-                        if (opcode > 201) {

-                            // converts temporary opcodes 202 to 217, 218 and

-                            // 219 to IFEQ ... JSR (inclusive), IFNULL and

-                            // IFNONNULL

-                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;

-                            label = u + readUnsignedShort(b, u + 1);

-                        } else {

-                            label = u + readShort(b, u + 1);

-                        }

-                        newOffset = getNewOffset(allIndexes, allSizes, u, label);

-                        if (newOffset < Short.MIN_VALUE

-                                || newOffset > Short.MAX_VALUE)

-                        {

-                            if (!resize[u]) {

-                                if (opcode == Opcodes.GOTO

-                                        || opcode == Opcodes.JSR)

-                                {

-                                    // two additional bytes will be required to

-                                    // replace this GOTO or JSR instruction with

-                                    // a GOTO_W or a JSR_W

-                                    insert = 2;

-                                } else {

-                                    // five additional bytes will be required to

-                                    // replace this IFxxx <l> instruction with

-                                    // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx

-                                    // is the "opposite" opcode of IFxxx (i.e.,

-                                    // IFNE for IFEQ) and where <l'> designates

-                                    // the instruction just after the GOTO_W.

-                                    insert = 5;

-                                }

-                                resize[u] = true;

-                            }

-                        }

-                        u += 3;

-                        break;

-                    case ClassWriter.LABELW_INSN:

-                        u += 5;

-                        break;

-                    case ClassWriter.TABL_INSN:

-                        if (state == 1) {

-                            // true number of bytes to be added (or removed)

-                            // from this instruction = (future number of padding

-                            // bytes - current number of padding byte) -

-                            // previously over estimated variation =

-                            // = ((3 - newOffset%4) - (3 - u%4)) - u%4

-                            // = (-newOffset%4 + u%4) - u%4

-                            // = -(newOffset & 3)

-                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);

-                            insert = -(newOffset & 3);

-                        } else if (!resize[u]) {

-                            // over estimation of the number of bytes to be

-                            // added to this instruction = 3 - current number

-                            // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3

-                            insert = u & 3;

-                            resize[u] = true;

-                        }

-                        // skips instruction

-                        u = u + 4 - (u & 3);

-                        u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;

-                        break;

-                    case ClassWriter.LOOK_INSN:

-                        if (state == 1) {

-                            // like TABL_INSN

-                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);

-                            insert = -(newOffset & 3);

-                        } else if (!resize[u]) {

-                            // like TABL_INSN

-                            insert = u & 3;

-                            resize[u] = true;

-                        }

-                        // skips instruction

-                        u = u + 4 - (u & 3);

-                        u += 8 * readInt(b, u + 4) + 8;

-                        break;

-                    case ClassWriter.WIDE_INSN:

-                        opcode = b[u + 1] & 0xFF;

-                        if (opcode == Opcodes.IINC) {

-                            u += 6;

-                        } else {

-                            u += 4;

-                        }

-                        break;

-                    case ClassWriter.VAR_INSN:

-                    case ClassWriter.SBYTE_INSN:

-                    case ClassWriter.LDC_INSN:

-                        u += 2;

-                        break;

-                    case ClassWriter.SHORT_INSN:

-                    case ClassWriter.LDCW_INSN:

-                    case ClassWriter.FIELDORMETH_INSN:

-                    case ClassWriter.TYPE_INSN:

-                    case ClassWriter.IINC_INSN:

-                        u += 3;

-                        break;

-                    case ClassWriter.ITFMETH_INSN:

-                        u += 5;

-                        break;

-                    // case ClassWriter.MANA_INSN:

-                    default:

-                        u += 4;

-                        break;

-                }

-                if (insert != 0) {

-                    // adds a new (u, insert) entry in the allIndexes and

-                    // allSizes arrays

-                    int[] newIndexes = new int[allIndexes.length + 1];

-                    int[] newSizes = new int[allSizes.length + 1];

-                    System.arraycopy(allIndexes,

-                            0,

-                            newIndexes,

-                            0,

-                            allIndexes.length);

-                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);

-                    newIndexes[allIndexes.length] = u;

-                    newSizes[allSizes.length] = insert;

-                    allIndexes = newIndexes;

-                    allSizes = newSizes;

-                    if (insert > 0) {

-                        state = 3;

-                    }

-                }

-            }

-            if (state < 3) {

-                --state;

-            }

-        } while (state != 0);

-

-        // 2nd step:

-        // copies the bytecode of the method into a new bytevector, updates the

-        // offsets, and inserts (or removes) bytes as requested.

-

-        ByteVector newCode = new ByteVector(code.length);

-

-        u = 0;

-        while (u < code.length) {

-            int opcode = b[u] & 0xFF;

-            switch (ClassWriter.TYPE[opcode]) {

-                case ClassWriter.NOARG_INSN:

-                case ClassWriter.IMPLVAR_INSN:

-                    newCode.putByte(opcode);

-                    u += 1;

-                    break;

-                case ClassWriter.LABEL_INSN:

-                    if (opcode > 201) {

-                        // changes temporary opcodes 202 to 217 (inclusive), 218

-                        // and 219 to IFEQ ... JSR (inclusive), IFNULL and

-                        // IFNONNULL

-                        opcode = opcode < 218 ? opcode - 49 : opcode - 20;

-                        label = u + readUnsignedShort(b, u + 1);

-                    } else {

-                        label = u + readShort(b, u + 1);

-                    }

-                    newOffset = getNewOffset(allIndexes, allSizes, u, label);

-                    if (resize[u]) {

-                        // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx

-                        // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is

-                        // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)

-                        // and where <l'> designates the instruction just after

-                        // the GOTO_W.

-                        if (opcode == Opcodes.GOTO) {

-                            newCode.putByte(200); // GOTO_W

-                        } else if (opcode == Opcodes.JSR) {

-                            newCode.putByte(201); // JSR_W

-                        } else {

-                            newCode.putByte(opcode <= 166

-                                    ? ((opcode + 1) ^ 1) - 1

-                                    : opcode ^ 1);

-                            newCode.putShort(8); // jump offset

-                            newCode.putByte(200); // GOTO_W

-                            // newOffset now computed from start of GOTO_W

-                            newOffset -= 3;

-                        }

-                        newCode.putInt(newOffset);

-                    } else {

-                        newCode.putByte(opcode);

-                        newCode.putShort(newOffset);

-                    }

-                    u += 3;

-                    break;

-                case ClassWriter.LABELW_INSN:

-                    label = u + readInt(b, u + 1);

-                    newOffset = getNewOffset(allIndexes, allSizes, u, label);

-                    newCode.putByte(opcode);

-                    newCode.putInt(newOffset);

-                    u += 5;

-                    break;

-                case ClassWriter.TABL_INSN:

-                    // skips 0 to 3 padding bytes

-                    v = u;

-                    u = u + 4 - (v & 3);

-                    // reads and copies instruction

-                    newCode.putByte(Opcodes.TABLESWITCH);

-                    newCode.length += (4 - newCode.length % 4) % 4;

-                    label = v + readInt(b, u);

-                    u += 4;

-                    newOffset = getNewOffset(allIndexes, allSizes, v, label);

-                    newCode.putInt(newOffset);

-                    j = readInt(b, u);

-                    u += 4;

-                    newCode.putInt(j);

-                    j = readInt(b, u) - j + 1;

-                    u += 4;

-                    newCode.putInt(readInt(b, u - 4));

-                    for (; j > 0; --j) {

-                        label = v + readInt(b, u);

-                        u += 4;

-                        newOffset = getNewOffset(allIndexes, allSizes, v, label);

-                        newCode.putInt(newOffset);

-                    }

-                    break;

-                case ClassWriter.LOOK_INSN:

-                    // skips 0 to 3 padding bytes

-                    v = u;

-                    u = u + 4 - (v & 3);

-                    // reads and copies instruction

-                    newCode.putByte(Opcodes.LOOKUPSWITCH);

-                    newCode.length += (4 - newCode.length % 4) % 4;

-                    label = v + readInt(b, u);

-                    u += 4;

-                    newOffset = getNewOffset(allIndexes, allSizes, v, label);

-                    newCode.putInt(newOffset);

-                    j = readInt(b, u);

-                    u += 4;

-                    newCode.putInt(j);

-                    for (; j > 0; --j) {

-                        newCode.putInt(readInt(b, u));

-                        u += 4;

-                        label = v + readInt(b, u);

-                        u += 4;

-                        newOffset = getNewOffset(allIndexes, allSizes, v, label);

-                        newCode.putInt(newOffset);

-                    }

-                    break;

-                case ClassWriter.WIDE_INSN:

-                    opcode = b[u + 1] & 0xFF;

-                    if (opcode == Opcodes.IINC) {

-                        newCode.putByteArray(b, u, 6);

-                        u += 6;

-                    } else {

-                        newCode.putByteArray(b, u, 4);

-                        u += 4;

-                    }

-                    break;

-                case ClassWriter.VAR_INSN:

-                case ClassWriter.SBYTE_INSN:

-                case ClassWriter.LDC_INSN:

-                    newCode.putByteArray(b, u, 2);

-                    u += 2;

-                    break;

-                case ClassWriter.SHORT_INSN:

-                case ClassWriter.LDCW_INSN:

-                case ClassWriter.FIELDORMETH_INSN:

-                case ClassWriter.TYPE_INSN:

-                case ClassWriter.IINC_INSN:

-                    newCode.putByteArray(b, u, 3);

-                    u += 3;

-                    break;

-                case ClassWriter.ITFMETH_INSN:

-                    newCode.putByteArray(b, u, 5);

-                    u += 5;

-                    break;

-                // case MANA_INSN:

-                default:

-                    newCode.putByteArray(b, u, 4);

-                    u += 4;

-                    break;

-            }

-        }

-

-        // recomputes the stack map frames

-        if (frameCount > 0) {

-            if (compute == FRAMES) {

-                frameCount = 0;

-                stackMap = null;

-                previousFrame = null;

-                frame = null;

-                Frame f = new Frame();

-                f.owner = labels;

-                Type[] args = Type.getArgumentTypes(descriptor);

-                f.initInputFrame(cw, access, args, maxLocals);

-                visitFrame(f);

-                Label l = labels;

-                while (l != null) {

-                    /*

-                     * here we need the original label position. getNewOffset

-                     * must therefore never have been called for this label.

-                     */

-                    u = l.position - 3;

-                    if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))

-                    {

-                        getNewOffset(allIndexes, allSizes, l);

-                        // TODO update offsets in UNINITIALIZED values

-                        visitFrame(l.frame);

-                    }

-                    l = l.successor;

-                }

-            } else {

-                /*

-                 * Resizing an existing stack map frame table is really hard.

-                 * Not only the table must be parsed to update the offets, but

-                 * new frames may be needed for jump instructions that were

-                 * inserted by this method. And updating the offsets or

-                 * inserting frames can change the format of the following

-                 * frames, in case of packed frames. In practice the whole table

-                 * must be recomputed. For this the frames are marked as

-                 * potentially invalid. This will cause the whole class to be

-                 * reread and rewritten with the COMPUTE_FRAMES option (see the

-                 * ClassWriter.toByteArray method). This is not very efficient

-                 * but is much easier and requires much less code than any other

-                 * method I can think of.

-                 */

-                cw.invalidFrames = true;

-            }

-        }

-        // updates the exception handler block labels

-        Handler h = firstHandler;

-        while (h != null) {

-            getNewOffset(allIndexes, allSizes, h.start);

-            getNewOffset(allIndexes, allSizes, h.end);

-            getNewOffset(allIndexes, allSizes, h.handler);

-            h = h.next;

-        }

-        // updates the instructions addresses in the

-        // local var and line number tables

-        for (i = 0; i < 2; ++i) {

-            ByteVector bv = i == 0 ? localVar : localVarType;

-            if (bv != null) {

-                b = bv.data;

-                u = 0;

-                while (u < bv.length) {

-                    label = readUnsignedShort(b, u);

-                    newOffset = getNewOffset(allIndexes, allSizes, 0, label);

-                    writeShort(b, u, newOffset);

-                    label += readUnsignedShort(b, u + 2);

-                    newOffset = getNewOffset(allIndexes, allSizes, 0, label)

-                            - newOffset;

-                    writeShort(b, u + 2, newOffset);

-                    u += 10;

-                }

-            }

-        }

-        if (lineNumber != null) {

-            b = lineNumber.data;

-            u = 0;

-            while (u < lineNumber.length) {

-                writeShort(b, u, getNewOffset(allIndexes,

-                        allSizes,

-                        0,

-                        readUnsignedShort(b, u)));

-                u += 4;

-            }

-        }

-        // updates the labels of the other attributes

-        Attribute attr = cattrs;

-        while (attr != null) {

-            Label[] labels = attr.getLabels();

-            if (labels != null) {

-                for (i = labels.length - 1; i >= 0; --i) {

-                    getNewOffset(allIndexes, allSizes, labels[i]);

-                }

-            }

-            attr = attr.next;

-        }

-

-        // replaces old bytecodes with new ones

-        code = newCode;

-    }

-

-    /**

-     * Reads an unsigned short value in the given byte array.

-     * 

-     * @param b a byte array.

-     * @param index the start index of the value to be read.

-     * @return the read value.

-     */

-    static int readUnsignedShort(final byte[] b, final int index) {

-        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);

-    }

-

-    /**

-     * Reads a signed short value in the given byte array.

-     * 

-     * @param b a byte array.

-     * @param index the start index of the value to be read.

-     * @return the read value.

-     */

-    static short readShort(final byte[] b, final int index) {

-        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));

-    }

-

-    /**

-     * Reads a signed int value in the given byte array.

-     * 

-     * @param b a byte array.

-     * @param index the start index of the value to be read.

-     * @return the read value.

-     */

-    static int readInt(final byte[] b, final int index) {

-        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)

-                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);

-    }

-

-    /**

-     * Writes a short value in the given byte array.

-     * 

-     * @param b a byte array.

-     * @param index where the first byte of the short value must be written.

-     * @param s the value to be written in the given byte array.

-     */

-    static void writeShort(final byte[] b, final int index, final int s) {

-        b[index] = (byte) (s >>> 8);

-        b[index + 1] = (byte) s;

-    }

-

-    /**

-     * Computes the future value of a bytecode offset. <p> Note: it is possible

-     * to have several entries for the same instruction in the <tt>indexes</tt>

-     * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')

-     * are equivalent to a single entry (index=a,size=b+b').

-     * 

-     * @param indexes current positions of the instructions to be resized. Each

-     *        instruction must be designated by the index of its <i>last</i>

-     *        byte, plus one (or, in other words, by the index of the <i>first</i>

-     *        byte of the <i>next</i> instruction).

-     * @param sizes the number of bytes to be <i>added</i> to the above

-     *        instructions. More precisely, for each i < <tt>len</tt>,

-     *        <tt>sizes</tt>[i] bytes will be added at the end of the

-     *        instruction designated by <tt>indexes</tt>[i] or, if

-     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|

-     *        bytes of the instruction will be removed (the instruction size

-     *        <i>must not</i> become negative or null).

-     * @param begin index of the first byte of the source instruction.

-     * @param end index of the first byte of the target instruction.

-     * @return the future value of the given bytecode offset.

-     */

-    static int getNewOffset(

-        final int[] indexes,

-        final int[] sizes,

-        final int begin,

-        final int end)

-    {

-        int offset = end - begin;

-        for (int i = 0; i < indexes.length; ++i) {

-            if (begin < indexes[i] && indexes[i] <= end) {

-                // forward jump

-                offset += sizes[i];

-            } else if (end < indexes[i] && indexes[i] <= begin) {

-                // backward jump

-                offset -= sizes[i];

-            }

-        }

-        return offset;

-    }

-

-    /**

-     * Updates the offset of the given label.

-     * 

-     * @param indexes current positions of the instructions to be resized. Each

-     *        instruction must be designated by the index of its <i>last</i>

-     *        byte, plus one (or, in other words, by the index of the <i>first</i>

-     *        byte of the <i>next</i> instruction).

-     * @param sizes the number of bytes to be <i>added</i> to the above

-     *        instructions. More precisely, for each i < <tt>len</tt>,

-     *        <tt>sizes</tt>[i] bytes will be added at the end of the

-     *        instruction designated by <tt>indexes</tt>[i] or, if

-     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|

-     *        bytes of the instruction will be removed (the instruction size

-     *        <i>must not</i> become negative or null).

-     * @param label the label whose offset must be updated.

-     */

-    static void getNewOffset(

-        final int[] indexes,

-        final int[] sizes,

-        final Label label)

-    {

-        if ((label.status & Label.RESIZED) == 0) {

-            label.position = getNewOffset(indexes, sizes, 0, label.position);

-            label.status |= Label.RESIZED;

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Opcodes.java b/cglib-and-asm/src/org/mockito/asm/Opcodes.java
deleted file mode 100644
index 0dce3bf..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Opcodes.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-/**

- * Defines the JVM opcodes, access flags and array type codes. This interface

- * does not define all the JVM opcodes because some opcodes are automatically

- * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced

- * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n

- * opcodes are therefore not defined in this interface. Likewise for LDC,

- * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and

- * JSR_W.

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public interface Opcodes {

-

-    // versions

-

-    int V1_1 = 3 << 16 | 45;

-    int V1_2 = 0 << 16 | 46;

-    int V1_3 = 0 << 16 | 47;

-    int V1_4 = 0 << 16 | 48;

-    int V1_5 = 0 << 16 | 49;

-    int V1_6 = 0 << 16 | 50;

-

-    // access flags

-

-    int ACC_PUBLIC = 0x0001; // class, field, method

-    int ACC_PRIVATE = 0x0002; // class, field, method

-    int ACC_PROTECTED = 0x0004; // class, field, method

-    int ACC_STATIC = 0x0008; // field, method

-    int ACC_FINAL = 0x0010; // class, field, method

-    int ACC_SUPER = 0x0020; // class

-    int ACC_SYNCHRONIZED = 0x0020; // method

-    int ACC_VOLATILE = 0x0040; // field

-    int ACC_BRIDGE = 0x0040; // method

-    int ACC_VARARGS = 0x0080; // method

-    int ACC_TRANSIENT = 0x0080; // field

-    int ACC_NATIVE = 0x0100; // method

-    int ACC_INTERFACE = 0x0200; // class

-    int ACC_ABSTRACT = 0x0400; // class, method

-    int ACC_STRICT = 0x0800; // method

-    int ACC_SYNTHETIC = 0x1000; // class, field, method

-    int ACC_ANNOTATION = 0x2000; // class

-    int ACC_ENUM = 0x4000; // class(?) field inner

-

-    // ASM specific pseudo access flags

-

-    int ACC_DEPRECATED = 131072; // class, field, method

-

-    // types for NEWARRAY

-

-    int T_BOOLEAN = 4;

-    int T_CHAR = 5;

-    int T_FLOAT = 6;

-    int T_DOUBLE = 7;

-    int T_BYTE = 8;

-    int T_SHORT = 9;

-    int T_INT = 10;

-    int T_LONG = 11;

-

-    // stack map frame types

-

-    /**

-     * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.

-     */

-    int F_NEW = -1;

-

-    /**

-     * Represents a compressed frame with complete frame data.

-     */

-    int F_FULL = 0;

-

-    /**

-     * Represents a compressed frame where locals are the same as the locals in

-     * the previous frame, except that additional 1-3 locals are defined, and

-     * with an empty stack.

-     */

-    int F_APPEND = 1;

-

-    /**

-     * Represents a compressed frame where locals are the same as the locals in

-     * the previous frame, except that the last 1-3 locals are absent and with

-     * an empty stack.

-     */

-    int F_CHOP = 2;

-

-    /**

-     * Represents a compressed frame with exactly the same locals as the

-     * previous frame and with an empty stack.

-     */

-    int F_SAME = 3;

-

-    /**

-     * Represents a compressed frame with exactly the same locals as the

-     * previous frame and with a single value on the stack.

-     */

-    int F_SAME1 = 4;

-

-    Integer TOP = new Integer(0);

-    Integer INTEGER = new Integer(1);

-    Integer FLOAT = new Integer(2);

-    Integer DOUBLE = new Integer(3);

-    Integer LONG = new Integer(4);

-    Integer NULL = new Integer(5);

-    Integer UNINITIALIZED_THIS = new Integer(6);

-

-    // opcodes // visit method (- = idem)

-

-    int NOP = 0; // visitInsn

-    int ACONST_NULL = 1; // -

-    int ICONST_M1 = 2; // -

-    int ICONST_0 = 3; // -

-    int ICONST_1 = 4; // -

-    int ICONST_2 = 5; // -

-    int ICONST_3 = 6; // -

-    int ICONST_4 = 7; // -

-    int ICONST_5 = 8; // -

-    int LCONST_0 = 9; // -

-    int LCONST_1 = 10; // -

-    int FCONST_0 = 11; // -

-    int FCONST_1 = 12; // -

-    int FCONST_2 = 13; // -

-    int DCONST_0 = 14; // -

-    int DCONST_1 = 15; // -

-    int BIPUSH = 16; // visitIntInsn

-    int SIPUSH = 17; // -

-    int LDC = 18; // visitLdcInsn

-    // int LDC_W = 19; // -

-    // int LDC2_W = 20; // -

-    int ILOAD = 21; // visitVarInsn

-    int LLOAD = 22; // -

-    int FLOAD = 23; // -

-    int DLOAD = 24; // -

-    int ALOAD = 25; // -

-    // int ILOAD_0 = 26; // -

-    // int ILOAD_1 = 27; // -

-    // int ILOAD_2 = 28; // -

-    // int ILOAD_3 = 29; // -

-    // int LLOAD_0 = 30; // -

-    // int LLOAD_1 = 31; // -

-    // int LLOAD_2 = 32; // -

-    // int LLOAD_3 = 33; // -

-    // int FLOAD_0 = 34; // -

-    // int FLOAD_1 = 35; // -

-    // int FLOAD_2 = 36; // -

-    // int FLOAD_3 = 37; // -

-    // int DLOAD_0 = 38; // -

-    // int DLOAD_1 = 39; // -

-    // int DLOAD_2 = 40; // -

-    // int DLOAD_3 = 41; // -

-    // int ALOAD_0 = 42; // -

-    // int ALOAD_1 = 43; // -

-    // int ALOAD_2 = 44; // -

-    // int ALOAD_3 = 45; // -

-    int IALOAD = 46; // visitInsn

-    int LALOAD = 47; // -

-    int FALOAD = 48; // -

-    int DALOAD = 49; // -

-    int AALOAD = 50; // -

-    int BALOAD = 51; // -

-    int CALOAD = 52; // -

-    int SALOAD = 53; // -

-    int ISTORE = 54; // visitVarInsn

-    int LSTORE = 55; // -

-    int FSTORE = 56; // -

-    int DSTORE = 57; // -

-    int ASTORE = 58; // -

-    // int ISTORE_0 = 59; // -

-    // int ISTORE_1 = 60; // -

-    // int ISTORE_2 = 61; // -

-    // int ISTORE_3 = 62; // -

-    // int LSTORE_0 = 63; // -

-    // int LSTORE_1 = 64; // -

-    // int LSTORE_2 = 65; // -

-    // int LSTORE_3 = 66; // -

-    // int FSTORE_0 = 67; // -

-    // int FSTORE_1 = 68; // -

-    // int FSTORE_2 = 69; // -

-    // int FSTORE_3 = 70; // -

-    // int DSTORE_0 = 71; // -

-    // int DSTORE_1 = 72; // -

-    // int DSTORE_2 = 73; // -

-    // int DSTORE_3 = 74; // -

-    // int ASTORE_0 = 75; // -

-    // int ASTORE_1 = 76; // -

-    // int ASTORE_2 = 77; // -

-    // int ASTORE_3 = 78; // -

-    int IASTORE = 79; // visitInsn

-    int LASTORE = 80; // -

-    int FASTORE = 81; // -

-    int DASTORE = 82; // -

-    int AASTORE = 83; // -

-    int BASTORE = 84; // -

-    int CASTORE = 85; // -

-    int SASTORE = 86; // -

-    int POP = 87; // -

-    int POP2 = 88; // -

-    int DUP = 89; // -

-    int DUP_X1 = 90; // -

-    int DUP_X2 = 91; // -

-    int DUP2 = 92; // -

-    int DUP2_X1 = 93; // -

-    int DUP2_X2 = 94; // -

-    int SWAP = 95; // -

-    int IADD = 96; // -

-    int LADD = 97; // -

-    int FADD = 98; // -

-    int DADD = 99; // -

-    int ISUB = 100; // -

-    int LSUB = 101; // -

-    int FSUB = 102; // -

-    int DSUB = 103; // -

-    int IMUL = 104; // -

-    int LMUL = 105; // -

-    int FMUL = 106; // -

-    int DMUL = 107; // -

-    int IDIV = 108; // -

-    int LDIV = 109; // -

-    int FDIV = 110; // -

-    int DDIV = 111; // -

-    int IREM = 112; // -

-    int LREM = 113; // -

-    int FREM = 114; // -

-    int DREM = 115; // -

-    int INEG = 116; // -

-    int LNEG = 117; // -

-    int FNEG = 118; // -

-    int DNEG = 119; // -

-    int ISHL = 120; // -

-    int LSHL = 121; // -

-    int ISHR = 122; // -

-    int LSHR = 123; // -

-    int IUSHR = 124; // -

-    int LUSHR = 125; // -

-    int IAND = 126; // -

-    int LAND = 127; // -

-    int IOR = 128; // -

-    int LOR = 129; // -

-    int IXOR = 130; // -

-    int LXOR = 131; // -

-    int IINC = 132; // visitIincInsn

-    int I2L = 133; // visitInsn

-    int I2F = 134; // -

-    int I2D = 135; // -

-    int L2I = 136; // -

-    int L2F = 137; // -

-    int L2D = 138; // -

-    int F2I = 139; // -

-    int F2L = 140; // -

-    int F2D = 141; // -

-    int D2I = 142; // -

-    int D2L = 143; // -

-    int D2F = 144; // -

-    int I2B = 145; // -

-    int I2C = 146; // -

-    int I2S = 147; // -

-    int LCMP = 148; // -

-    int FCMPL = 149; // -

-    int FCMPG = 150; // -

-    int DCMPL = 151; // -

-    int DCMPG = 152; // -

-    int IFEQ = 153; // visitJumpInsn

-    int IFNE = 154; // -

-    int IFLT = 155; // -

-    int IFGE = 156; // -

-    int IFGT = 157; // -

-    int IFLE = 158; // -

-    int IF_ICMPEQ = 159; // -

-    int IF_ICMPNE = 160; // -

-    int IF_ICMPLT = 161; // -

-    int IF_ICMPGE = 162; // -

-    int IF_ICMPGT = 163; // -

-    int IF_ICMPLE = 164; // -

-    int IF_ACMPEQ = 165; // -

-    int IF_ACMPNE = 166; // -

-    int GOTO = 167; // -

-    int JSR = 168; // -

-    int RET = 169; // visitVarInsn

-    int TABLESWITCH = 170; // visiTableSwitchInsn

-    int LOOKUPSWITCH = 171; // visitLookupSwitch

-    int IRETURN = 172; // visitInsn

-    int LRETURN = 173; // -

-    int FRETURN = 174; // -

-    int DRETURN = 175; // -

-    int ARETURN = 176; // -

-    int RETURN = 177; // -

-    int GETSTATIC = 178; // visitFieldInsn

-    int PUTSTATIC = 179; // -

-    int GETFIELD = 180; // -

-    int PUTFIELD = 181; // -

-    int INVOKEVIRTUAL = 182; // visitMethodInsn

-    int INVOKESPECIAL = 183; // -

-    int INVOKESTATIC = 184; // -

-    int INVOKEINTERFACE = 185; // -

-    // int UNUSED = 186; // NOT VISITED

-    int NEW = 187; // visitTypeInsn

-    int NEWARRAY = 188; // visitIntInsn

-    int ANEWARRAY = 189; // visitTypeInsn

-    int ARRAYLENGTH = 190; // visitInsn

-    int ATHROW = 191; // -

-    int CHECKCAST = 192; // visitTypeInsn

-    int INSTANCEOF = 193; // -

-    int MONITORENTER = 194; // visitInsn

-    int MONITOREXIT = 195; // -

-    // int WIDE = 196; // NOT VISITED

-    int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn

-    int IFNULL = 198; // visitJumpInsn

-    int IFNONNULL = 199; // -

-    // int GOTO_W = 200; // -

-    // int JSR_W = 201; // -

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/Type.java b/cglib-and-asm/src/org/mockito/asm/Type.java
deleted file mode 100644
index 5ab06b4..0000000
--- a/cglib-and-asm/src/org/mockito/asm/Type.java
+++ /dev/null
@@ -1,794 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm;

-

-import java.lang.reflect.Constructor;

-import java.lang.reflect.Method;

-

-/**

- * A Java type. This class can be used to make it easier to manipulate type and

- * method descriptors.

- * 

- * @author Eric Bruneton

- * @author Chris Nokleberg

- */

-public class Type {

-

-    /**

-     * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int VOID = 0;

-

-    /**

-     * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int BOOLEAN = 1;

-

-    /**

-     * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int CHAR = 2;

-

-    /**

-     * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int BYTE = 3;

-

-    /**

-     * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int SHORT = 4;

-

-    /**

-     * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int INT = 5;

-

-    /**

-     * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int FLOAT = 6;

-

-    /**

-     * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int LONG = 7;

-

-    /**

-     * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.

-     */

-    public static final int DOUBLE = 8;

-

-    /**

-     * The sort of array reference types. See {@link #getSort getSort}.

-     */

-    public static final int ARRAY = 9;

-

-    /**

-     * The sort of object reference type. See {@link #getSort getSort}.

-     */

-    public static final int OBJECT = 10;

-

-    /**

-     * The <tt>void</tt> type.

-     */

-    public static final Type VOID_TYPE = new Type(VOID);

-

-    /**

-     * The <tt>boolean</tt> type.

-     */

-    public static final Type BOOLEAN_TYPE = new Type(BOOLEAN);

-

-    /**

-     * The <tt>char</tt> type.

-     */

-    public static final Type CHAR_TYPE = new Type(CHAR);

-

-    /**

-     * The <tt>byte</tt> type.

-     */

-    public static final Type BYTE_TYPE = new Type(BYTE);

-

-    /**

-     * The <tt>short</tt> type.

-     */

-    public static final Type SHORT_TYPE = new Type(SHORT);

-

-    /**

-     * The <tt>int</tt> type.

-     */

-    public static final Type INT_TYPE = new Type(INT);

-

-    /**

-     * The <tt>float</tt> type.

-     */

-    public static final Type FLOAT_TYPE = new Type(FLOAT);

-

-    /**

-     * The <tt>long</tt> type.

-     */

-    public static final Type LONG_TYPE = new Type(LONG);

-

-    /**

-     * The <tt>double</tt> type.

-     */

-    public static final Type DOUBLE_TYPE = new Type(DOUBLE);

-

-    // ------------------------------------------------------------------------

-    // Fields

-    // ------------------------------------------------------------------------

-

-    /**

-     * The sort of this Java type.

-     */

-    private final int sort;

-

-    /**

-     * A buffer containing the internal name of this Java type. This field is

-     * only used for reference types.

-     */

-    private final char[] buf;

-

-    /**

-     * The offset of the internal name of this Java type in {@link #buf buf}.

-     * This field is only used for reference types.

-     */

-    private final int off;

-

-    /**

-     * The length of the internal name of this Java type. This field is only

-     * used for reference types.

-     */

-    private final int len;

-

-    // ------------------------------------------------------------------------

-    // Constructors

-    // ------------------------------------------------------------------------

-

-    /**

-     * Constructs a primitive type.

-     * 

-     * @param sort the sort of the primitive type to be constructed.

-     */

-    private Type(final int sort) {

-        this(sort, null, 0, 1);

-    }

-

-    /**

-     * Constructs a reference type.

-     * 

-     * @param sort the sort of the reference type to be constructed.

-     * @param buf a buffer containing the descriptor of the previous type.

-     * @param off the offset of this descriptor in the previous buffer.

-     * @param len the length of this descriptor.

-     */

-    private Type(final int sort, final char[] buf, final int off, final int len)

-    {

-        this.sort = sort;

-        this.buf = buf;

-        this.off = off;

-        this.len = len;

-    }

-

-    /**

-     * Returns the Java type corresponding to the given type descriptor.

-     * 

-     * @param typeDescriptor a type descriptor.

-     * @return the Java type corresponding to the given type descriptor.

-     */

-    public static Type getType(final String typeDescriptor) {

-        return getType(typeDescriptor.toCharArray(), 0);

-    }

-

-    /**

-     * Returns the Java type corresponding to the given internal name.

-     * 

-     * @param internalName an internal name.

-     * @return the Java type corresponding to the given internal name.

-     */

-    public static Type getObjectType(final String internalName) {

-        char[] buf = internalName.toCharArray();

-        return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);

-    }

-

-    /**

-     * Returns the Java type corresponding to the given class.

-     * 

-     * @param c a class.

-     * @return the Java type corresponding to the given class.

-     */

-    public static Type getType(final Class c) {

-        if (c.isPrimitive()) {

-            if (c == Integer.TYPE) {

-                return INT_TYPE;

-            } else if (c == Void.TYPE) {

-                return VOID_TYPE;

-            } else if (c == Boolean.TYPE) {

-                return BOOLEAN_TYPE;

-            } else if (c == Byte.TYPE) {

-                return BYTE_TYPE;

-            } else if (c == Character.TYPE) {

-                return CHAR_TYPE;

-            } else if (c == Short.TYPE) {

-                return SHORT_TYPE;

-            } else if (c == Double.TYPE) {

-                return DOUBLE_TYPE;

-            } else if (c == Float.TYPE) {

-                return FLOAT_TYPE;

-            } else /* if (c == Long.TYPE) */{

-                return LONG_TYPE;

-            }

-        } else {

-            return getType(getDescriptor(c));

-        }

-    }

-

-    /**

-     * Returns the Java types corresponding to the argument types of the given

-     * method descriptor.

-     * 

-     * @param methodDescriptor a method descriptor.

-     * @return the Java types corresponding to the argument types of the given

-     *         method descriptor.

-     */

-    public static Type[] getArgumentTypes(final String methodDescriptor) {

-        char[] buf = methodDescriptor.toCharArray();

-        int off = 1;

-        int size = 0;

-        while (true) {

-            char car = buf[off++];

-            if (car == ')') {

-                break;

-            } else if (car == 'L') {

-                while (buf[off++] != ';') {

-                }

-                ++size;

-            } else if (car != '[') {

-                ++size;

-            }

-        }

-        Type[] args = new Type[size];

-        off = 1;

-        size = 0;

-        while (buf[off] != ')') {

-            args[size] = getType(buf, off);

-            off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);

-            size += 1;

-        }

-        return args;

-    }

-

-    /**

-     * Returns the Java types corresponding to the argument types of the given

-     * method.

-     * 

-     * @param method a method.

-     * @return the Java types corresponding to the argument types of the given

-     *         method.

-     */

-    public static Type[] getArgumentTypes(final Method method) {

-        Class[] classes = method.getParameterTypes();

-        Type[] types = new Type[classes.length];

-        for (int i = classes.length - 1; i >= 0; --i) {

-            types[i] = getType(classes[i]);

-        }

-        return types;

-    }

-

-    /**

-     * Returns the Java type corresponding to the return type of the given

-     * method descriptor.

-     * 

-     * @param methodDescriptor a method descriptor.

-     * @return the Java type corresponding to the return type of the given

-     *         method descriptor.

-     */

-    public static Type getReturnType(final String methodDescriptor) {

-        char[] buf = methodDescriptor.toCharArray();

-        return getType(buf, methodDescriptor.indexOf(')') + 1);

-    }

-

-    /**

-     * Returns the Java type corresponding to the return type of the given

-     * method.

-     * 

-     * @param method a method.

-     * @return the Java type corresponding to the return type of the given

-     *         method.

-     */

-    public static Type getReturnType(final Method method) {

-        return getType(method.getReturnType());

-    }

-

-    /**

-     * Returns the Java type corresponding to the given type descriptor.

-     * 

-     * @param buf a buffer containing a type descriptor.

-     * @param off the offset of this descriptor in the previous buffer.

-     * @return the Java type corresponding to the given type descriptor.

-     */

-    private static Type getType(final char[] buf, final int off) {

-        int len;

-        switch (buf[off]) {

-            case 'V':

-                return VOID_TYPE;

-            case 'Z':

-                return BOOLEAN_TYPE;

-            case 'C':

-                return CHAR_TYPE;

-            case 'B':

-                return BYTE_TYPE;

-            case 'S':

-                return SHORT_TYPE;

-            case 'I':

-                return INT_TYPE;

-            case 'F':

-                return FLOAT_TYPE;

-            case 'J':

-                return LONG_TYPE;

-            case 'D':

-                return DOUBLE_TYPE;

-            case '[':

-                len = 1;

-                while (buf[off + len] == '[') {

-                    ++len;

-                }

-                if (buf[off + len] == 'L') {

-                    ++len;

-                    while (buf[off + len] != ';') {

-                        ++len;

-                    }

-                }

-                return new Type(ARRAY, buf, off, len + 1);

-                // case 'L':

-            default:

-                len = 1;

-                while (buf[off + len] != ';') {

-                    ++len;

-                }

-                return new Type(OBJECT, buf, off + 1, len - 1);

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Accessors

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the sort of this Java type.

-     * 

-     * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},

-     *         {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},

-     *         {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},

-     *         {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or

-     *         {@link #OBJECT OBJECT}.

-     */

-    public int getSort() {

-        return sort;

-    }

-

-    /**

-     * Returns the number of dimensions of this array type. This method should

-     * only be used for an array type.

-     * 

-     * @return the number of dimensions of this array type.

-     */

-    public int getDimensions() {

-        int i = 1;

-        while (buf[off + i] == '[') {

-            ++i;

-        }

-        return i;

-    }

-

-    /**

-     * Returns the type of the elements of this array type. This method should

-     * only be used for an array type.

-     * 

-     * @return Returns the type of the elements of this array type.

-     */

-    public Type getElementType() {

-        return getType(buf, off + getDimensions());

-    }

-

-    /**

-     * Returns the name of the class corresponding to this type.

-     * 

-     * @return the fully qualified name of the class corresponding to this type.

-     */

-    public String getClassName() {

-        switch (sort) {

-            case VOID:

-                return "void";

-            case BOOLEAN:

-                return "boolean";

-            case CHAR:

-                return "char";

-            case BYTE:

-                return "byte";

-            case SHORT:

-                return "short";

-            case INT:

-                return "int";

-            case FLOAT:

-                return "float";

-            case LONG:

-                return "long";

-            case DOUBLE:

-                return "double";

-            case ARRAY:

-                StringBuffer b = new StringBuffer(getElementType().getClassName());

-                for (int i = getDimensions(); i > 0; --i) {

-                    b.append("[]");

-                }

-                return b.toString();

-                // case OBJECT:

-            default:

-                return new String(buf, off, len).replace('/', '.');

-        }

-    }

-

-    /**

-     * Returns the internal name of the class corresponding to this object or

-     * array type. The internal name of a class is its fully qualified name (as

-     * returned by Class.getName(), where '.' are replaced by '/'. This method

-     * should only be used for an object or array type.

-     * 

-     * @return the internal name of the class corresponding to this object type.

-     */

-    public String getInternalName() {

-        return new String(buf, off, len);

-    }

-

-    // ------------------------------------------------------------------------

-    // Conversion to type descriptors

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the descriptor corresponding to this Java type.

-     * 

-     * @return the descriptor corresponding to this Java type.

-     */

-    public String getDescriptor() {

-        StringBuffer buf = new StringBuffer();

-        getDescriptor(buf);

-        return buf.toString();

-    }

-

-    /**

-     * Returns the descriptor corresponding to the given argument and return

-     * types.

-     * 

-     * @param returnType the return type of the method.

-     * @param argumentTypes the argument types of the method.

-     * @return the descriptor corresponding to the given argument and return

-     *         types.

-     */

-    public static String getMethodDescriptor(

-        final Type returnType,

-        final Type[] argumentTypes)

-    {

-        StringBuffer buf = new StringBuffer();

-        buf.append('(');

-        for (int i = 0; i < argumentTypes.length; ++i) {

-            argumentTypes[i].getDescriptor(buf);

-        }

-        buf.append(')');

-        returnType.getDescriptor(buf);

-        return buf.toString();

-    }

-

-    /**

-     * Appends the descriptor corresponding to this Java type to the given

-     * string buffer.

-     * 

-     * @param buf the string buffer to which the descriptor must be appended.

-     */

-    private void getDescriptor(final StringBuffer buf) {

-        switch (sort) {

-            case VOID:

-                buf.append('V');

-                return;

-            case BOOLEAN:

-                buf.append('Z');

-                return;

-            case CHAR:

-                buf.append('C');

-                return;

-            case BYTE:

-                buf.append('B');

-                return;

-            case SHORT:

-                buf.append('S');

-                return;

-            case INT:

-                buf.append('I');

-                return;

-            case FLOAT:

-                buf.append('F');

-                return;

-            case LONG:

-                buf.append('J');

-                return;

-            case DOUBLE:

-                buf.append('D');

-                return;

-            case ARRAY:

-                buf.append(this.buf, off, len);

-                return;

-                // case OBJECT:

-            default:

-                buf.append('L');

-                buf.append(this.buf, off, len);

-                buf.append(';');

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Direct conversion from classes to type descriptors,

-    // without intermediate Type objects

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the internal name of the given class. The internal name of a

-     * class is its fully qualified name, as returned by Class.getName(), where

-     * '.' are replaced by '/'.

-     * 

-     * @param c an object or array class.

-     * @return the internal name of the given class.

-     */

-    public static String getInternalName(final Class c) {

-        return c.getName().replace('.', '/');

-    }

-

-    /**

-     * Returns the descriptor corresponding to the given Java type.

-     * 

-     * @param c an object class, a primitive class or an array class.

-     * @return the descriptor corresponding to the given class.

-     */

-    public static String getDescriptor(final Class c) {

-        StringBuffer buf = new StringBuffer();

-        getDescriptor(buf, c);

-        return buf.toString();

-    }

-

-    /**

-     * Returns the descriptor corresponding to the given constructor.

-     * 

-     * @param c a {@link Constructor Constructor} object.

-     * @return the descriptor of the given constructor.

-     */

-    public static String getConstructorDescriptor(final Constructor c) {

-        Class[] parameters = c.getParameterTypes();

-        StringBuffer buf = new StringBuffer();

-        buf.append('(');

-        for (int i = 0; i < parameters.length; ++i) {

-            getDescriptor(buf, parameters[i]);

-        }

-        return buf.append(")V").toString();

-    }

-

-    /**

-     * Returns the descriptor corresponding to the given method.

-     * 

-     * @param m a {@link Method Method} object.

-     * @return the descriptor of the given method.

-     */

-    public static String getMethodDescriptor(final Method m) {

-        Class[] parameters = m.getParameterTypes();

-        StringBuffer buf = new StringBuffer();

-        buf.append('(');

-        for (int i = 0; i < parameters.length; ++i) {

-            getDescriptor(buf, parameters[i]);

-        }

-        buf.append(')');

-        getDescriptor(buf, m.getReturnType());

-        return buf.toString();

-    }

-

-    /**

-     * Appends the descriptor of the given class to the given string buffer.

-     * 

-     * @param buf the string buffer to which the descriptor must be appended.

-     * @param c the class whose descriptor must be computed.

-     */

-    private static void getDescriptor(final StringBuffer buf, final Class c) {

-        Class d = c;

-        while (true) {

-            if (d.isPrimitive()) {

-                char car;

-                if (d == Integer.TYPE) {

-                    car = 'I';

-                } else if (d == Void.TYPE) {

-                    car = 'V';

-                } else if (d == Boolean.TYPE) {

-                    car = 'Z';

-                } else if (d == Byte.TYPE) {

-                    car = 'B';

-                } else if (d == Character.TYPE) {

-                    car = 'C';

-                } else if (d == Short.TYPE) {

-                    car = 'S';

-                } else if (d == Double.TYPE) {

-                    car = 'D';

-                } else if (d == Float.TYPE) {

-                    car = 'F';

-                } else /* if (d == Long.TYPE) */{

-                    car = 'J';

-                }

-                buf.append(car);

-                return;

-            } else if (d.isArray()) {

-                buf.append('[');

-                d = d.getComponentType();

-            } else {

-                buf.append('L');

-                String name = d.getName();

-                int len = name.length();

-                for (int i = 0; i < len; ++i) {

-                    char car = name.charAt(i);

-                    buf.append(car == '.' ? '/' : car);

-                }

-                buf.append(';');

-                return;

-            }

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Corresponding size and opcodes

-    // ------------------------------------------------------------------------

-

-    /**

-     * Returns the size of values of this type.

-     * 

-     * @return the size of values of this type, i.e., 2 for <tt>long</tt> and

-     *         <tt>double</tt>, and 1 otherwise.

-     */

-    public int getSize() {

-        return sort == LONG || sort == DOUBLE ? 2 : 1;

-    }

-

-    /**

-     * Returns a JVM instruction opcode adapted to this Java type.

-     * 

-     * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,

-     *        ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,

-     *        ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.

-     * @return an opcode that is similar to the given opcode, but adapted to

-     *         this Java type. For example, if this type is <tt>float</tt> and

-     *         <tt>opcode</tt> is IRETURN, this method returns FRETURN.

-     */

-    public int getOpcode(final int opcode) {

-        if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {

-            switch (sort) {

-                case BOOLEAN:

-                case BYTE:

-                    return opcode + 5;

-                case CHAR:

-                    return opcode + 6;

-                case SHORT:

-                    return opcode + 7;

-                case INT:

-                    return opcode;

-                case FLOAT:

-                    return opcode + 2;

-                case LONG:

-                    return opcode + 1;

-                case DOUBLE:

-                    return opcode + 3;

-                    // case ARRAY:

-                    // case OBJECT:

-                default:

-                    return opcode + 4;

-            }

-        } else {

-            switch (sort) {

-                case VOID:

-                    return opcode + 5;

-                case BOOLEAN:

-                case CHAR:

-                case BYTE:

-                case SHORT:

-                case INT:

-                    return opcode;

-                case FLOAT:

-                    return opcode + 2;

-                case LONG:

-                    return opcode + 1;

-                case DOUBLE:

-                    return opcode + 3;

-                    // case ARRAY:

-                    // case OBJECT:

-                default:

-                    return opcode + 4;

-            }

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Equals, hashCode and toString

-    // ------------------------------------------------------------------------

-

-    /**

-     * Tests if the given object is equal to this type.

-     * 

-     * @param o the object to be compared to this type.

-     * @return <tt>true</tt> if the given object is equal to this type.

-     */

-    public boolean equals(final Object o) {

-        if (this == o) {

-            return true;

-        }

-        if (!(o instanceof Type)) {

-            return false;

-        }

-        Type t = (Type) o;

-        if (sort != t.sort) {

-            return false;

-        }

-        if (sort == OBJECT || sort == ARRAY) {

-            if (len != t.len) {

-                return false;

-            }

-            for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {

-                if (buf[i] != t.buf[j]) {

-                    return false;

-                }

-            }

-        }

-        return true;

-    }

-

-    /**

-     * Returns a hash code value for this type.

-     * 

-     * @return a hash code value for this type.

-     */

-    public int hashCode() {

-        int hc = 13 * sort;

-        if (sort == OBJECT || sort == ARRAY) {

-            for (int i = off, end = i + len; i < end; i++) {

-                hc = 17 * (hc + buf[i]);

-            }

-        }

-        return hc;

-    }

-

-    /**

-     * Returns a string representation of this type.

-     * 

-     * @return the descriptor of this type.

-     */

-    public String toString() {

-        return getDescriptor();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/package.html b/cglib-and-asm/src/org/mockito/asm/package.html
deleted file mode 100644
index b87e4f2..0000000
--- a/cglib-and-asm/src/org/mockito/asm/package.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<html>

-<!--

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2005 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

--->

-<body>

-Provides a small and fast bytecode manipulation framework.

-

-<p>

-The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized

-around the {@link org.objectweb.asm.ClassVisitor ClassVisitor}, 

-{@link org.objectweb.asm.FieldVisitor FieldVisitor} and 

-{@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces, which allow

-one to visit the fields and methods of a class, including the bytecode 

-instructions of each method.

-

-<p>

-In addition to these main interfaces, ASM provides a {@link

-org.objectweb.asm.ClassReader ClassReader} class, that can parse an

-existing class and make a given visitor visit it. ASM also provides

-a {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is

-a visitor that generates Java class files.

-

-<p>

-In order to generate a class from scratch, only the {@link

-org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,

-in order to generate a class, one must just call its visit<i>XXX</i>

-methods with the appropriate arguments to generate the desired fields

-and methods. See the "helloworld" example in the ASM distribution for

-more details about class generation.

-

-<p>

-In order to modify existing classes, one must use a {@link

-org.objectweb.asm.ClassReader ClassReader} class to analyze

-the original class, a class modifier, and a {@link org.objectweb.asm.ClassWriter

-ClassWriter} to construct the modified class. The class modifier

-is just a {@link org.objectweb.asm.ClassVisitor ClassVisitor}

-that delegates most of the work to another {@link org.objectweb.asm.ClassVisitor

-ClassVisitor}, but that sometimes changes some parameter values,

-or call additional methods, in order to implement the desired

-modification process. In order to make it easier to implement such

-class modifiers, ASM provides the {@link org.objectweb.asm.ClassAdapter

-ClassAdapter} and {@link org.objectweb.asm.MethodAdapter MethodAdapter}

-classes, which implement the {@link org.objectweb.asm.ClassVisitor ClassVisitor} 

-and {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces by 

-delegating all work to other visitors. See the "adapt" example in the ASM 

-distribution for more details about class modification.

-

-<p>

-The size of the core ASM library, <tt>asm.jar</tt>, is only 42KB, which is much

-smaller than the size of the 

-<a href="http://jakarta.apache.org/bcel">BCEL</a> library (504KB), and than the 

-size of the

-<a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also

-much faster than these tools. Indeed the overhead of a load time class

-transformation process is of the order of 60% with ASM, 700% or more with BCEL,

-and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM

-distribution)!

-

-@since ASM 1.3

-</body>

-</html>

diff --git a/cglib-and-asm/src/org/mockito/asm/signature/SignatureReader.java b/cglib-and-asm/src/org/mockito/asm/signature/SignatureReader.java
deleted file mode 100644
index 5f07eb8..0000000
--- a/cglib-and-asm/src/org/mockito/asm/signature/SignatureReader.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.signature;

-

-/**

- * A type signature parser to make a signature visitor visit an existing

- * signature.

- * 

- * @author Thomas Hallgren

- * @author Eric Bruneton

- */

-public class SignatureReader {

-

-    /**

-     * The signature to be read.

-     */

-    private final String signature;

-

-    /**

-     * Constructs a {@link SignatureReader} for the given signature.

-     * 

-     * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,

-     *        or <i>FieldTypeSignature</i>.

-     */

-    public SignatureReader(final String signature) {

-        this.signature = signature;

-    }

-

-    /**

-     * Makes the given visitor visit the signature of this

-     * {@link SignatureReader}. This signature is the one specified in the

-     * constructor (see {@link #SignatureReader(String) SignatureReader}). This

-     * method is intended to be called on a {@link SignatureReader} that was

-     * created using a <i>ClassSignature</i> (such as the

-     * <code>signature</code> parameter of the

-     * {@link org.mockito.asm.ClassVisitor#visit ClassVisitor.visit} method)

-     * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>

-     * parameter of the

-     * {@link org.mockito.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}

-     * method).

-     * 

-     * @param v the visitor that must visit this signature.

-     */

-    public void accept(final SignatureVisitor v) {

-        String signature = this.signature;

-        int len = signature.length();

-        int pos;

-        char c;

-

-        if (signature.charAt(0) == '<') {

-            pos = 2;

-            do {

-                int end = signature.indexOf(':', pos);

-                v.visitFormalTypeParameter(signature.substring(pos - 1, end));

-                pos = end + 1;

-

-                c = signature.charAt(pos);

-                if (c == 'L' || c == '[' || c == 'T') {

-                    pos = parseType(signature, pos, v.visitClassBound());

-                }

-

-                while ((c = signature.charAt(pos++)) == ':') {

-                    pos = parseType(signature, pos, v.visitInterfaceBound());

-                }

-            } while (c != '>');

-        } else {

-            pos = 0;

-        }

-

-        if (signature.charAt(pos) == '(') {

-            pos++;

-            while (signature.charAt(pos) != ')') {

-                pos = parseType(signature, pos, v.visitParameterType());

-            }

-            pos = parseType(signature, pos + 1, v.visitReturnType());

-            while (pos < len) {

-                pos = parseType(signature, pos + 1, v.visitExceptionType());

-            }

-        } else {

-            pos = parseType(signature, pos, v.visitSuperclass());

-            while (pos < len) {

-                pos = parseType(signature, pos, v.visitInterface());

-            }

-        }

-    }

-

-    /**

-     * Makes the given visitor visit the signature of this

-     * {@link SignatureReader}. This signature is the one specified in the

-     * constructor (see {@link #SignatureReader(String) SignatureReader}). This

-     * method is intended to be called on a {@link SignatureReader} that was

-     * created using a <i>FieldTypeSignature</i>, such as the

-     * <code>signature</code> parameter of the

-     * {@link org.mockito.asm.ClassVisitor#visitField 

-     * ClassVisitor.visitField} or {@link 

-     * org.mockito.asm.MethodVisitor#visitLocalVariable

-     * MethodVisitor.visitLocalVariable} methods.

-     * 

-     * @param v the visitor that must visit this signature.

-     */

-    public void acceptType(final SignatureVisitor v) {

-        parseType(this.signature, 0, v);

-    }

-

-    /**

-     * Parses a field type signature and makes the given visitor visit it.

-     * 

-     * @param signature a string containing the signature that must be parsed.

-     * @param pos index of the first character of the signature to parsed.

-     * @param v the visitor that must visit this signature.

-     * @return the index of the first character after the parsed signature.

-     */

-    private static int parseType(

-        final String signature,

-        int pos,

-        final SignatureVisitor v)

-    {

-        char c;

-        int start, end;

-        boolean visited, inner;

-        String name;

-

-        switch (c = signature.charAt(pos++)) {

-            case 'Z':

-            case 'C':

-            case 'B':

-            case 'S':

-            case 'I':

-            case 'F':

-            case 'J':

-            case 'D':

-            case 'V':

-                v.visitBaseType(c);

-                return pos;

-

-            case '[':

-                return parseType(signature, pos, v.visitArrayType());

-

-            case 'T':

-                end = signature.indexOf(';', pos);

-                v.visitTypeVariable(signature.substring(pos, end));

-                return end + 1;

-

-            default: // case 'L':

-                start = pos;

-                visited = false;

-                inner = false;

-                for (;;) {

-                    switch (c = signature.charAt(pos++)) {

-                        case '.':

-                        case ';':

-                            if (!visited) {

-                                name = signature.substring(start, pos - 1);

-                                if (inner) {

-                                    v.visitInnerClassType(name);

-                                } else {

-                                    v.visitClassType(name);

-                                }

-                            }

-                            if (c == ';') {

-                                v.visitEnd();

-                                return pos;

-                            }

-                            start = pos;

-                            visited = false;

-                            inner = true;

-                            break;

-

-                        case '<':

-                            name = signature.substring(start, pos - 1);

-                            if (inner) {

-                                v.visitInnerClassType(name);

-                            } else {

-                                v.visitClassType(name);

-                            }

-                            visited = true;

-                            top: for (;;) {

-                                switch (c = signature.charAt(pos)) {

-                                    case '>':

-                                        break top;

-                                    case '*':

-                                        ++pos;

-                                        v.visitTypeArgument();

-                                        break;

-                                    case '+':

-                                    case '-':

-                                        pos = parseType(signature,

-                                                pos + 1,

-                                                v.visitTypeArgument(c));

-                                        break;

-                                    default:

-                                        pos = parseType(signature,

-                                                pos,

-                                                v.visitTypeArgument('='));

-                                        break;

-                                }

-                            }

-                    }

-                }

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/signature/SignatureVisitor.java b/cglib-and-asm/src/org/mockito/asm/signature/SignatureVisitor.java
deleted file mode 100644
index d943e92..0000000
--- a/cglib-and-asm/src/org/mockito/asm/signature/SignatureVisitor.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.signature;

-

-/**

- * A visitor to visit a generic signature. The methods of this interface must be

- * called in one of the three following orders (the last one is the only valid

- * order for a {@link SignatureVisitor} that is returned by a method of this

- * interface): <ul> <li><i>ClassSignature</i> = (

- * <tt>visitFormalTypeParameter</tt> 

- *   <tt>visitClassBound</tt>?

- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt> 

- *   <tt>visitInterface</tt>* )</li>

- * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> 

- *   <tt>visitClassBound</tt>?

- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*

- * <tt>visitReturnType</tt> 

- *   <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =

- * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |

- * <tt>visitArrayType</tt> | (

- * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (

- * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*

- * <tt>visitEnd</tt> ) )</li> </ul>

- * 

- * @author Thomas Hallgren

- * @author Eric Bruneton

- */

-public interface SignatureVisitor {

-

-    /**

-     * Wildcard for an "extends" type argument.

-     */

-    char EXTENDS = '+';

-

-    /**

-     * Wildcard for a "super" type argument.

-     */

-    char SUPER = '-';

-

-    /**

-     * Wildcard for a normal type argument.

-     */

-    char INSTANCEOF = '=';

-

-    /**

-     * Visits a formal type parameter.

-     * 

-     * @param name the name of the formal parameter.

-     */

-    void visitFormalTypeParameter(String name);

-

-    /**

-     * Visits the class bound of the last visited formal type parameter.

-     * 

-     * @return a non null visitor to visit the signature of the class bound.

-     */

-    SignatureVisitor visitClassBound();

-

-    /**

-     * Visits an interface bound of the last visited formal type parameter.

-     * 

-     * @return a non null visitor to visit the signature of the interface bound.

-     */

-    SignatureVisitor visitInterfaceBound();

-

-    /**

-     * Visits the type of the super class.

-     * 

-     * @return a non null visitor to visit the signature of the super class

-     *         type.

-     */

-    SignatureVisitor visitSuperclass();

-

-    /**

-     * Visits the type of an interface implemented by the class.

-     * 

-     * @return a non null visitor to visit the signature of the interface type.

-     */

-    SignatureVisitor visitInterface();

-

-    /**

-     * Visits the type of a method parameter.

-     * 

-     * @return a non null visitor to visit the signature of the parameter type.

-     */

-    SignatureVisitor visitParameterType();

-

-    /**

-     * Visits the return type of the method.

-     * 

-     * @return a non null visitor to visit the signature of the return type.

-     */

-    SignatureVisitor visitReturnType();

-

-    /**

-     * Visits the type of a method exception.

-     * 

-     * @return a non null visitor to visit the signature of the exception type.

-     */

-    SignatureVisitor visitExceptionType();

-

-    /**

-     * Visits a signature corresponding to a primitive type.

-     * 

-     * @param descriptor the descriptor of the primitive type, or 'V' for

-     *        <tt>void</tt>.

-     */

-    void visitBaseType(char descriptor);

-

-    /**

-     * Visits a signature corresponding to a type variable.

-     * 

-     * @param name the name of the type variable.

-     */

-    void visitTypeVariable(String name);

-

-    /**

-     * Visits a signature corresponding to an array type.

-     * 

-     * @return a non null visitor to visit the signature of the array element

-     *         type.

-     */

-    SignatureVisitor visitArrayType();

-

-    /**

-     * Starts the visit of a signature corresponding to a class or interface

-     * type.

-     * 

-     * @param name the internal name of the class or interface.

-     */

-    void visitClassType(String name);

-

-    /**

-     * Visits an inner class.

-     * 

-     * @param name the local name of the inner class in its enclosing class.

-     */

-    void visitInnerClassType(String name);

-

-    /**

-     * Visits an unbounded type argument of the last visited class or inner

-     * class type.

-     */

-    void visitTypeArgument();

-

-    /**

-     * Visits a type argument of the last visited class or inner class type.

-     * 

-     * @param wildcard '+', '-' or '='.

-     * @return a non null visitor to visit the signature of the type argument.

-     */

-    SignatureVisitor visitTypeArgument(char wildcard);

-

-    /**

-     * Ends the visit of a signature corresponding to a class or interface type.

-     */

-    void visitEnd();

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/signature/SignatureWriter.java b/cglib-and-asm/src/org/mockito/asm/signature/SignatureWriter.java
deleted file mode 100644
index 77f2da9..0000000
--- a/cglib-and-asm/src/org/mockito/asm/signature/SignatureWriter.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.signature;

-

-/**

- * A signature visitor that generates signatures in string format.

- * 

- * @author Thomas Hallgren

- * @author Eric Bruneton

- */

-public class SignatureWriter implements SignatureVisitor {

-

-    /**

-     * Buffer used to construct the signature.

-     */

-    private final StringBuffer buf = new StringBuffer();

-

-    /**

-     * Indicates if the signature contains formal type parameters.

-     */

-    private boolean hasFormals;

-

-    /**

-     * Indicates if the signature contains method parameter types.

-     */

-    private boolean hasParameters;

-

-    /**

-     * Stack used to keep track of class types that have arguments. Each element

-     * of this stack is a boolean encoded in one bit. The top of the stack is

-     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =

-     * /2.

-     */

-    private int argumentStack;

-

-    /**

-     * Constructs a new {@link SignatureWriter} object.

-     */

-    public SignatureWriter() {

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the SignatureVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visitFormalTypeParameter(final String name) {

-        if (!hasFormals) {

-            hasFormals = true;

-            buf.append('<');

-        }

-        buf.append(name);

-        buf.append(':');

-    }

-

-    public SignatureVisitor visitClassBound() {

-        return this;

-    }

-

-    public SignatureVisitor visitInterfaceBound() {

-        buf.append(':');

-        return this;

-    }

-

-    public SignatureVisitor visitSuperclass() {

-        endFormals();

-        return this;

-    }

-

-    public SignatureVisitor visitInterface() {

-        return this;

-    }

-

-    public SignatureVisitor visitParameterType() {

-        endFormals();

-        if (!hasParameters) {

-            hasParameters = true;

-            buf.append('(');

-        }

-        return this;

-    }

-

-    public SignatureVisitor visitReturnType() {

-        endFormals();

-        if (!hasParameters) {

-            buf.append('(');

-        }

-        buf.append(')');

-        return this;

-    }

-

-    public SignatureVisitor visitExceptionType() {

-        buf.append('^');

-        return this;

-    }

-

-    public void visitBaseType(final char descriptor) {

-        buf.append(descriptor);

-    }

-

-    public void visitTypeVariable(final String name) {

-        buf.append('T');

-        buf.append(name);

-        buf.append(';');

-    }

-

-    public SignatureVisitor visitArrayType() {

-        buf.append('[');

-        return this;

-    }

-

-    public void visitClassType(final String name) {

-        buf.append('L');

-        buf.append(name);

-        argumentStack *= 2;

-    }

-

-    public void visitInnerClassType(final String name) {

-        endArguments();

-        buf.append('.');

-        buf.append(name);

-        argumentStack *= 2;

-    }

-

-    public void visitTypeArgument() {

-        if (argumentStack % 2 == 0) {

-            ++argumentStack;

-            buf.append('<');

-        }

-        buf.append('*');

-    }

-

-    public SignatureVisitor visitTypeArgument(final char wildcard) {

-        if (argumentStack % 2 == 0) {

-            ++argumentStack;

-            buf.append('<');

-        }

-        if (wildcard != '=') {

-            buf.append(wildcard);

-        }

-        return this;

-    }

-

-    public void visitEnd() {

-        endArguments();

-        buf.append(';');

-    }

-

-    /**

-     * Returns the signature that was built by this signature writer.

-     * 

-     * @return the signature that was built by this signature writer.

-     */

-    public String toString() {

-        return buf.toString();

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Ends the formal type parameters section of the signature.

-     */

-    private void endFormals() {

-        if (hasFormals) {

-            hasFormals = false;

-            buf.append('>');

-        }

-    }

-

-    /**

-     * Ends the type arguments of a class or inner class type.

-     */

-    private void endArguments() {

-        if (argumentStack % 2 != 0) {

-            buf.append('>');

-        }

-        argumentStack /= 2;

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/signature/package.html b/cglib-and-asm/src/org/mockito/asm/signature/package.html
deleted file mode 100644
index b9de4cf..0000000
--- a/cglib-and-asm/src/org/mockito/asm/signature/package.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<html>

-<!--

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2005 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

--->

-<body>

-Provides support for type signatures.

-

-@since ASM 2.0

-</body>

-</html>

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/AbstractInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/AbstractInsnNode.java
deleted file mode 100644
index 191777a..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/AbstractInsnNode.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.List;

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a bytecode instruction. <i>An instruction can appear

- * at most once in at most one {@link InsnList} at a time</i>.

- * 

- * @author Eric Bruneton

- */

-public abstract class AbstractInsnNode {

-

-    /**

-     * The type of {@link InsnNode} instructions.

-     */

-    public static final int INSN = 0;

-

-    /**

-     * The type of {@link IntInsnNode} instructions.

-     */

-    public static final int INT_INSN = 1;

-

-    /**

-     * The type of {@link VarInsnNode} instructions.

-     */

-    public static final int VAR_INSN = 2;

-

-    /**

-     * The type of {@link TypeInsnNode} instructions.

-     */

-    public static final int TYPE_INSN = 3;

-

-    /**

-     * The type of {@link FieldInsnNode} instructions.

-     */

-    public static final int FIELD_INSN = 4;

-

-    /**

-     * The type of {@link MethodInsnNode} instructions.

-     */

-    public static final int METHOD_INSN = 5;

-

-    /**

-     * The type of {@link JumpInsnNode} instructions.

-     */

-    public static final int JUMP_INSN = 6;

-

-    /**

-     * The type of {@link LabelNode} "instructions".

-     */

-    public static final int LABEL = 7;

-

-    /**

-     * The type of {@link LdcInsnNode} instructions.

-     */

-    public static final int LDC_INSN = 8;

-

-    /**

-     * The type of {@link IincInsnNode} instructions.

-     */

-    public static final int IINC_INSN = 9;

-

-    /**

-     * The type of {@link TableSwitchInsnNode} instructions.

-     */

-    public static final int TABLESWITCH_INSN = 10;

-

-    /**

-     * The type of {@link LookupSwitchInsnNode} instructions.

-     */

-    public static final int LOOKUPSWITCH_INSN = 11;

-

-    /**

-     * The type of {@link MultiANewArrayInsnNode} instructions.

-     */

-    public static final int MULTIANEWARRAY_INSN = 12;

-

-    /**

-     * The type of {@link FrameNode} "instructions".

-     */

-    public static final int FRAME = 13;

-

-    /**

-     * The type of {@link LineNumberNode} "instructions".

-     */

-    public static final int LINE = 14;

-

-    /**

-     * The opcode of this instruction.

-     */

-    protected int opcode;

-

-    /**

-     * Previous instruction in the list to which this instruction belongs.

-     */

-    AbstractInsnNode prev;

-

-    /**

-     * Next instruction in the list to which this instruction belongs.

-     */

-    AbstractInsnNode next;

-

-    /**

-     * Index of this instruction in the list to which it belongs. The value of

-     * this field is correct only when {@link InsnList#cache} is not null. A

-     * value of -1 indicates that this instruction does not belong to any

-     * {@link InsnList}.

-     */

-    int index;

-

-    /**

-     * Constructs a new {@link AbstractInsnNode}.

-     * 

-     * @param opcode the opcode of the instruction to be constructed.

-     */

-    protected AbstractInsnNode(final int opcode) {

-        this.opcode = opcode;

-        this.index = -1;

-    }

-

-    /**

-     * Returns the opcode of this instruction.

-     * 

-     * @return the opcode of this instruction.

-     */

-    public int getOpcode() {

-        return opcode;

-    }

-

-    /**

-     * Returns the type of this instruction.

-     * 

-     * @return the type of this instruction, i.e. one the constants defined in

-     *         this class.

-     */

-    public abstract int getType();

-

-    /**

-     * Returns the previous instruction in the list to which this instruction

-     * belongs, if any.

-     * 

-     * @return the previous instruction in the list to which this instruction

-     *         belongs, if any. May be <tt>null</tt>.

-     */

-    public AbstractInsnNode getPrevious() {

-        return prev;

-    }

-

-    /**

-     * Returns the next instruction in the list to which this instruction

-     * belongs, if any.

-     * 

-     * @return the next instruction in the list to which this instruction

-     *         belongs, if any. May be <tt>null</tt>.

-     */

-    public AbstractInsnNode getNext() {

-        return next;

-    }

-

-    /**

-     * Makes the given code visitor visit this instruction.

-     * 

-     * @param cv a code visitor.

-     */

-    public abstract void accept(final MethodVisitor cv);

-

-    /**

-     * Returns a copy of this instruction.

-     * 

-     * @param labels a map from LabelNodes to cloned LabelNodes.

-     * @return a copy of this instruction. The returned instruction does not

-     *         belong to any {@link InsnList}.

-     */

-    public abstract AbstractInsnNode clone(final Map labels);

-

-    /**

-     * Returns the clone of the given label.

-     * 

-     * @param label a label.

-     * @param map a map from LabelNodes to cloned LabelNodes.

-     * @return the clone of the given label.

-     */

-    static LabelNode clone(final LabelNode label, final Map map) {

-        return (LabelNode) map.get(label);

-    }

-

-    /**

-     * Returns the clones of the given labels.

-     * 

-     * @param labels a list of labels.

-     * @param map a map from LabelNodes to cloned LabelNodes.

-     * @return the clones of the given labels.

-     */

-    static LabelNode[] clone(final List labels, final Map map) {

-        LabelNode[] clones = new LabelNode[labels.size()];

-        for (int i = 0; i < clones.length; ++i) {

-            clones[i] = (LabelNode) map.get(labels.get(i));

-        }

-        return clones;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/AnnotationNode.java b/cglib-and-asm/src/org/mockito/asm/tree/AnnotationNode.java
deleted file mode 100644
index 092c0a5..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/AnnotationNode.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.ArrayList;

-import java.util.List;

-

-import org.mockito.asm.AnnotationVisitor;

-

-/**

- * A node that represents an annotationn.

- * 

- * @author Eric Bruneton

- */

-public class AnnotationNode implements AnnotationVisitor {

-

-    /**

-     * The class descriptor of the annotation class.

-     */

-    public String desc;

-

-    /**

-     * The name value pairs of this annotation. Each name value pair is stored

-     * as two consecutive elements in the list. The name is a {@link String},

-     * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},

-     * {@link Short}, {@link Integer}, {@link Long}, {@link Float},

-     * {@link Double}, {@link String} or {@link org.mockito.asm.Type}, or an

-     * two elements String array (for enumeration values), a

-     * {@link AnnotationNode}, or a {@link List} of values of one of the

-     * preceding types. The list may be <tt>null</tt> if there is no name

-     * value pair.

-     */

-    public List values;

-

-    /**

-     * Constructs a new {@link AnnotationNode}.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     */

-    public AnnotationNode(final String desc) {

-        this.desc = desc;

-    }

-

-    /**

-     * Constructs a new {@link AnnotationNode} to visit an array value.

-     * 

-     * @param values where the visited values must be stored.

-     */

-    AnnotationNode(final List values) {

-        this.values = values;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the AnnotationVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(final String name, final Object value) {

-        if (values == null) {

-            values = new ArrayList(this.desc != null ? 2 : 1);

-        }

-        if (this.desc != null) {

-            values.add(name);

-        }

-        values.add(value);

-    }

-

-    public void visitEnum(

-        final String name,

-        final String desc,

-        final String value)

-    {

-        if (values == null) {

-            values = new ArrayList(this.desc != null ? 2 : 1);

-        }

-        if (this.desc != null) {

-            values.add(name);

-        }

-        values.add(new String[] { desc, value });

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String name,

-        final String desc)

-    {

-        if (values == null) {

-            values = new ArrayList(this.desc != null ? 2 : 1);

-        }

-        if (this.desc != null) {

-            values.add(name);

-        }

-        AnnotationNode annotation = new AnnotationNode(desc);

-        values.add(annotation);

-        return annotation;

-    }

-

-    public AnnotationVisitor visitArray(final String name) {

-        if (values == null) {

-            values = new ArrayList(this.desc != null ? 2 : 1);

-        }

-        if (this.desc != null) {

-            values.add(name);

-        }

-        List array = new ArrayList();

-        values.add(array);

-        return new AnnotationNode(array);

-    }

-

-    public void visitEnd() {

-    }

-

-    // ------------------------------------------------------------------------

-    // Accept methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Makes the given visitor visit this annotation.

-     * 

-     * @param av an annotation visitor. Maybe <tt>null</tt>.

-     */

-    public void accept(final AnnotationVisitor av) {

-        if (av != null) {

-            if (values != null) {

-                for (int i = 0; i < values.size(); i += 2) {

-                    String name = (String) values.get(i);

-                    Object value = values.get(i + 1);

-                    accept(av, name, value);

-                }

-            }

-            av.visitEnd();

-        }

-    }

-

-    /**

-     * Makes the given visitor visit a given annotation value.

-     * 

-     * @param av an annotation visitor. Maybe <tt>null</tt>.

-     * @param name the value name.

-     * @param value the actual value.

-     */

-    static void accept(

-        final AnnotationVisitor av,

-        final String name,

-        final Object value)

-    {

-        if (av != null) {

-            if (value instanceof String[]) {

-                String[] typeconst = (String[]) value;

-                av.visitEnum(name, typeconst[0], typeconst[1]);

-            } else if (value instanceof AnnotationNode) {

-                AnnotationNode an = (AnnotationNode) value;

-                an.accept(av.visitAnnotation(name, an.desc));

-            } else if (value instanceof List) {

-                AnnotationVisitor v = av.visitArray(name);

-                List array = (List) value;

-                for (int j = 0; j < array.size(); ++j) {

-                    accept(v, null, array.get(j));

-                }

-                v.visitEnd();

-            } else {

-                av.visit(name, value);

-            }

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/ClassNode.java b/cglib-and-asm/src/org/mockito/asm/tree/ClassNode.java
deleted file mode 100644
index 452d8ef..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/ClassNode.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.Attribute;

-import org.mockito.asm.ClassVisitor;

-import org.mockito.asm.FieldVisitor;

-import org.mockito.asm.MethodVisitor;

-

-import java.util.List;

-import java.util.ArrayList;

-import java.util.Arrays;

-

-/**

- * A node that represents a class.

- * 

- * @author Eric Bruneton

- */

-public class ClassNode extends MemberNode implements ClassVisitor {

-

-    /**

-     * The class version.

-     */

-    public int version;

-

-    /**

-     * The class's access flags (see {@link org.mockito.asm.Opcodes}). This

-     * field also indicates if the class is deprecated.

-     */

-    public int access;

-

-    /**

-     * The internal name of the class (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     */

-    public String name;

-

-    /**

-     * The signature of the class. Mayt be <tt>null</tt>.

-     */

-    public String signature;

-

-    /**

-     * The internal of name of the super class (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}). For

-     * interfaces, the super class is {@link Object}. May be <tt>null</tt>,

-     * but only for the {@link Object} class.

-     */

-    public String superName;

-

-    /**

-     * The internal names of the class's interfaces (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}). This

-     * list is a list of {@link String} objects.

-     */

-    public List interfaces;

-

-    /**

-     * The name of the source file from which this class was compiled. May be

-     * <tt>null</tt>.

-     */

-    public String sourceFile;

-

-    /**

-     * Debug information to compute the correspondance between source and

-     * compiled elements of the class. May be <tt>null</tt>.

-     */

-    public String sourceDebug;

-

-    /**

-     * The internal name of the enclosing class of the class. May be

-     * <tt>null</tt>.

-     */

-    public String outerClass;

-

-    /**

-     * The name of the method that contains the class, or <tt>null</tt> if the

-     * class is not enclosed in a method.

-     */

-    public String outerMethod;

-

-    /**

-     * The descriptor of the method that contains the class, or <tt>null</tt>

-     * if the class is not enclosed in a method.

-     */

-    public String outerMethodDesc;

-

-    /**

-     * Informations about the inner classes of this class. This list is a list

-     * of {@link InnerClassNode} objects.

-     * 

-     * @associates org.mockito.asm.tree.InnerClassNode

-     */

-    public List innerClasses;

-

-    /**

-     * The fields of this class. This list is a list of {@link FieldNode}

-     * objects.

-     * 

-     * @associates org.mockito.asm.tree.FieldNode

-     */

-    public List fields;

-

-    /**

-     * The methods of this class. This list is a list of {@link MethodNode}

-     * objects.

-     * 

-     * @associates org.mockito.asm.tree.MethodNode

-     */

-    public List methods;

-

-    /**

-     * Constructs a new {@link ClassNode}.

-     */

-    public ClassNode() {

-        this.interfaces = new ArrayList();

-        this.innerClasses = new ArrayList();

-        this.fields = new ArrayList();

-        this.methods = new ArrayList();

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the ClassVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(

-        final int version,

-        final int access,

-        final String name,

-        final String signature,

-        final String superName,

-        final String[] interfaces)

-    {

-        this.version = version;

-        this.access = access;

-        this.name = name;

-        this.signature = signature;

-        this.superName = superName;

-        if (interfaces != null) {

-            this.interfaces.addAll(Arrays.asList(interfaces));

-        }

-    }

-

-    public void visitSource(final String file, final String debug) {

-        sourceFile = file;

-        sourceDebug = debug;

-    }

-

-    public void visitOuterClass(

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        outerClass = owner;

-        outerMethod = name;

-        outerMethodDesc = desc;

-    }

-

-    public void visitInnerClass(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        InnerClassNode icn = new InnerClassNode(name,

-                outerName,

-                innerName,

-                access);

-        innerClasses.add(icn);

-    }

-

-    public FieldVisitor visitField(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        FieldNode fn = new FieldNode(access, name, desc, signature, value);

-        fields.add(fn);

-        return fn;

-    }

-

-    public MethodVisitor visitMethod(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        MethodNode mn = new MethodNode(access,

-                name,

-                desc,

-                signature,

-                exceptions);

-        methods.add(mn);

-        return mn;

-    }

-

-    // ------------------------------------------------------------------------

-    // Accept method

-    // ------------------------------------------------------------------------

-

-    /**

-     * Makes the given class visitor visit this class.

-     * 

-     * @param cv a class visitor.

-     */

-    public void accept(final ClassVisitor cv) {

-        // visits header

-        String[] interfaces = new String[this.interfaces.size()];

-        this.interfaces.toArray(interfaces);

-        cv.visit(version, access, name, signature, superName, interfaces);

-        // visits source

-        if (sourceFile != null || sourceDebug != null) {

-            cv.visitSource(sourceFile, sourceDebug);

-        }

-        // visits outer class

-        if (outerClass != null) {

-            cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);

-        }

-        // visits attributes

-        int i, n;

-        n = visibleAnnotations == null ? 0 : visibleAnnotations.size();

-        for (i = 0; i < n; ++i) {

-            AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);

-            an.accept(cv.visitAnnotation(an.desc, true));

-        }

-        n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();

-        for (i = 0; i < n; ++i) {

-            AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);

-            an.accept(cv.visitAnnotation(an.desc, false));

-        }

-        n = attrs == null ? 0 : attrs.size();

-        for (i = 0; i < n; ++i) {

-            cv.visitAttribute((Attribute) attrs.get(i));

-        }

-        // visits inner classes

-        for (i = 0; i < innerClasses.size(); ++i) {

-            ((InnerClassNode) innerClasses.get(i)).accept(cv);

-        }

-        // visits fields

-        for (i = 0; i < fields.size(); ++i) {

-            ((FieldNode) fields.get(i)).accept(cv);

-        }

-        // visits methods

-        for (i = 0; i < methods.size(); ++i) {

-            ((MethodNode) methods.get(i)).accept(cv);

-        }

-        // visits end

-        cv.visitEnd();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/FieldInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/FieldInsnNode.java
deleted file mode 100644
index cec597f..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/FieldInsnNode.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a field instruction. A field instruction is an

- * instruction that loads or stores the value of a field of an object.

- * 

- * @author Eric Bruneton

- */

-public class FieldInsnNode extends AbstractInsnNode {

-

-    /**

-     * The internal name of the field's owner class (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     */

-    public String owner;

-

-    /**

-     * The field's name.

-     */

-    public String name;

-

-    /**

-     * The field's descriptor (see {@link org.mockito.asm.Type}).

-     */

-    public String desc;

-

-    /**

-     * Constructs a new {@link FieldInsnNode}.

-     * 

-     * @param opcode the opcode of the type instruction to be constructed. This

-     *        opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.

-     * @param owner the internal name of the field's owner class (see

-     *        {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     * @param name the field's name.

-     * @param desc the field's descriptor (see {@link org.mockito.asm.Type}).

-     */

-    public FieldInsnNode(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        super(opcode);

-        this.owner = owner;

-        this.name = name;

-        this.desc = desc;

-    }

-

-    /**

-     * Sets the opcode of this instruction.

-     * 

-     * @param opcode the new instruction opcode. This opcode must be GETSTATIC,

-     *        PUTSTATIC, GETFIELD or PUTFIELD.

-     */

-    public void setOpcode(final int opcode) {

-        this.opcode = opcode;

-    }

-

-    public int getType() {

-        return FIELD_INSN;

-    }

-

-    public void accept(final MethodVisitor cv) {

-        cv.visitFieldInsn(opcode, owner, name, desc);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new FieldInsnNode(opcode, owner, name, desc);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/FieldNode.java b/cglib-and-asm/src/org/mockito/asm/tree/FieldNode.java
deleted file mode 100644
index 4414f2f..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/FieldNode.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.Attribute;

-import org.mockito.asm.ClassVisitor;

-import org.mockito.asm.FieldVisitor;

-

-/**

- * A node that represents a field.

- * 

- * @author Eric Bruneton

- */

-public class FieldNode extends MemberNode implements FieldVisitor {

-

-    /**

-     * The field's access flags (see {@link org.mockito.asm.Opcodes}). This

-     * field also indicates if the field is synthetic and/or deprecated.

-     */

-    public int access;

-

-    /**

-     * The field's name.

-     */

-    public String name;

-

-    /**

-     * The field's descriptor (see {@link org.mockito.asm.Type}).

-     */

-    public String desc;

-

-    /**

-     * The field's signature. May be <tt>null</tt>.

-     */

-    public String signature;

-

-    /**

-     * The field's initial value. This field, which may be <tt>null</tt> if

-     * the field does not have an initial value, must be an {@link Integer}, a

-     * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.

-     */

-    public Object value;

-

-    /**

-     * Constructs a new {@link FieldNode}.

-     * 

-     * @param access the field's access flags (see

-     *        {@link org.mockito.asm.Opcodes}). This parameter also indicates

-     *        if the field is synthetic and/or deprecated.

-     * @param name the field's name.

-     * @param desc the field's descriptor (see

-     *        {@link org.mockito.asm.Type Type}).

-     * @param signature the field's signature.

-     * @param value the field's initial value. This parameter, which may be

-     *        <tt>null</tt> if the field does not have an initial value, must

-     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a

-     *        {@link Double} or a {@link String}.

-     */

-    public FieldNode(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        this.access = access;

-        this.name = name;

-        this.desc = desc;

-        this.signature = signature;

-        this.value = value;

-    }

-

-    /**

-     * Makes the given class visitor visit this field.

-     * 

-     * @param cv a class visitor.

-     */

-    public void accept(final ClassVisitor cv) {

-        FieldVisitor fv = cv.visitField(access, name, desc, signature, value);

-        if (fv == null) {

-            return;

-        }

-        int i, n;

-        n = visibleAnnotations == null ? 0 : visibleAnnotations.size();

-        for (i = 0; i < n; ++i) {

-            AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);

-            an.accept(fv.visitAnnotation(an.desc, true));

-        }

-        n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();

-        for (i = 0; i < n; ++i) {

-            AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);

-            an.accept(fv.visitAnnotation(an.desc, false));

-        }

-        n = attrs == null ? 0 : attrs.size();

-        for (i = 0; i < n; ++i) {

-            fv.visitAttribute((Attribute) attrs.get(i));

-        }

-        fv.visitEnd();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/FrameNode.java b/cglib-and-asm/src/org/mockito/asm/tree/FrameNode.java
deleted file mode 100644
index 603dbca..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/FrameNode.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.ArrayList;

-import java.util.Arrays;

-import java.util.List;

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-/**

- * A node that represents a stack map frame. These nodes are pseudo instruction

- * nodes in order to be inserted in an instruction list. In fact these nodes

- * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that

- * follows an unconditionnal branch instruction such as GOTO or THROW, that is

- * the target of a jump instruction, or that starts an exception handler block.

- * The stack map frame types must describe the values of the local variables and

- * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>

- * <br> (*) this is mandatory only for classes whose version is greater than or

- * equal to {@link Opcodes#V1_6 V1_6}.

- * 

- * @author Eric Bruneton

- */

-public class FrameNode extends AbstractInsnNode {

-

-    /**

-     * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded

-     * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},

-     * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or

-     * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.

-     */

-    public int type;

-

-    /**

-     * The types of the local variables of this stack map frame. Elements of

-     * this list can be Integer, String or LabelNode objects (for primitive,

-     * reference and uninitialized types respectively - see

-     * {@link MethodVisitor}).

-     */

-    public List local;

-

-    /**

-     * The types of the operand stack elements of this stack map frame. Elements

-     * of this list can be Integer, String or LabelNode objects (for primitive,

-     * reference and uninitialized types respectively - see

-     * {@link MethodVisitor}).

-     */

-    public List stack;

-

-    private FrameNode() {

-        super(-1);

-    }

-

-    /**

-     * Constructs a new {@link FrameNode}.

-     * 

-     * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for

-     *        expanded frames, or {@link Opcodes#F_FULL},

-     *        {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},

-     *        {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},

-     *        {@link Opcodes#F_SAME1} for compressed frames.

-     * @param nLocal number of local variables of this stack map frame.

-     * @param local the types of the local variables of this stack map frame.

-     *        Elements of this list can be Integer, String or LabelNode objects

-     *        (for primitive, reference and uninitialized types respectively -

-     *        see {@link MethodVisitor}).

-     * @param nStack number of operand stack elements of this stack map frame.

-     * @param stack the types of the operand stack elements of this stack map

-     *        frame. Elements of this list can be Integer, String or LabelNode

-     *        objects (for primitive, reference and uninitialized types

-     *        respectively - see {@link MethodVisitor}).

-     */

-    public FrameNode(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        super(-1);

-        this.type = type;

-        switch (type) {

-            case Opcodes.F_NEW:

-            case Opcodes.F_FULL:

-                this.local = asList(nLocal, local);

-                this.stack = asList(nStack, stack);

-                break;

-            case Opcodes.F_APPEND:

-                this.local = asList(nLocal, local);

-                break;

-            case Opcodes.F_CHOP:

-                this.local = asList(nLocal, local);

-                break;

-            case Opcodes.F_SAME:

-                break;

-            case Opcodes.F_SAME1:

-                this.stack = asList(1, stack);

-                break;

-        }

-    }

-

-    public int getType() {

-        return FRAME;

-    }

-

-    /**

-     * Makes the given visitor visit this stack map frame.

-     * 

-     * @param mv a method visitor.

-     */

-    public void accept(final MethodVisitor mv) {

-        switch (type) {

-            case Opcodes.F_NEW:

-            case Opcodes.F_FULL:

-                mv.visitFrame(type,

-                        local.size(),

-                        asArray(local),

-                        stack.size(),

-                        asArray(stack));

-                break;

-            case Opcodes.F_APPEND:

-                mv.visitFrame(type, local.size(), asArray(local), 0, null);

-                break;

-            case Opcodes.F_CHOP:

-                mv.visitFrame(type, local.size(), asArray(local), 0, null);

-                break;

-            case Opcodes.F_SAME:

-                mv.visitFrame(type, 0, null, 0, null);

-                break;

-            case Opcodes.F_SAME1:

-                mv.visitFrame(type, 0, null, 1, asArray(stack));

-                break;

-        }

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        FrameNode clone = new FrameNode();

-        clone.type = type;

-        if (local != null) {

-            clone.local = new ArrayList();

-            for (int i = 0; i < local.size(); ++i) {

-                Object l = local.get(i);

-                if (l instanceof LabelNode) {

-                    l = labels.get(l);

-                }

-                clone.local.add(l);

-            }

-        }

-        if (stack != null) {

-            clone.stack = new ArrayList();

-            for (int i = 0; i < stack.size(); ++i) {

-                Object s = stack.get(i);

-                if (s instanceof LabelNode) {

-                    s = labels.get(s);

-                }

-                clone.stack.add(s);

-            }

-        }

-        return clone;

-    }

-

-    // ------------------------------------------------------------------------

-

-    private static List asList(final int n, final Object[] o) {

-        return Arrays.asList(o).subList(0, n);

-    }

-

-    private static Object[] asArray(final List l) {

-        Object[] objs = new Object[l.size()];

-        for (int i = 0; i < objs.length; ++i) {

-            Object o = l.get(i);

-            if (o instanceof LabelNode) {

-                o = ((LabelNode) o).getLabel();

-            }

-            objs[i] = o;

-        }

-        return objs;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/IincInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/IincInsnNode.java
deleted file mode 100644
index f9989c0..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/IincInsnNode.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-/**

- * A node that represents an IINC instruction.

- * 

- * @author Eric Bruneton

- */

-public class IincInsnNode extends AbstractInsnNode {

-

-    /**

-     * Index of the local variable to be incremented.

-     */

-    public int var;

-

-    /**

-     * Amount to increment the local variable by.

-     */

-    public int incr;

-

-    /**

-     * Constructs a new {@link IincInsnNode}.

-     * 

-     * @param var index of the local variable to be incremented.

-     * @param incr increment amount to increment the local variable by.

-     */

-    public IincInsnNode(final int var, final int incr) {

-        super(Opcodes.IINC);

-        this.var = var;

-        this.incr = incr;

-    }

-

-    public int getType() {

-        return IINC_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitIincInsn(var, incr);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new IincInsnNode(var, incr);

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/InnerClassNode.java b/cglib-and-asm/src/org/mockito/asm/tree/InnerClassNode.java
deleted file mode 100644
index 10eb9a4..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/InnerClassNode.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.ClassVisitor;

-

-/**

- * A node that represents an inner class.

- * 

- * @author Eric Bruneton

- */

-public class InnerClassNode {

-

-    /**

-     * The internal name of an inner class (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     */

-    public String name;

-

-    /**

-     * The internal name of the class to which the inner class belongs (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}). May

-     * be <tt>null</tt>.

-     */

-    public String outerName;

-

-    /**

-     * The (simple) name of the inner class inside its enclosing class. May be

-     * <tt>null</tt> for anonymous inner classes.

-     */

-    public String innerName;

-

-    /**

-     * The access flags of the inner class as originally declared in the

-     * enclosing class.

-     */

-    public int access;

-

-    /**

-     * Constructs a new {@link InnerClassNode}.

-     * 

-     * @param name the internal name of an inner class (see

-     *        {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     * @param outerName the internal name of the class to which the inner class

-     *        belongs (see

-     *        {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     *        May be <tt>null</tt>.

-     * @param innerName the (simple) name of the inner class inside its

-     *        enclosing class. May be <tt>null</tt> for anonymous inner

-     *        classes.

-     * @param access the access flags of the inner class as originally declared

-     *        in the enclosing class.

-     */

-    public InnerClassNode(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        this.name = name;

-        this.outerName = outerName;

-        this.innerName = innerName;

-        this.access = access;

-    }

-

-    /**

-     * Makes the given class visitor visit this inner class.

-     * 

-     * @param cv a class visitor.

-     */

-    public void accept(final ClassVisitor cv) {

-        cv.visitInnerClass(name, outerName, innerName, access);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/InsnList.java b/cglib-and-asm/src/org/mockito/asm/tree/InsnList.java
deleted file mode 100644
index bd81c0f..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/InsnList.java
+++ /dev/null
@@ -1,640 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.ListIterator;

-import java.util.NoSuchElementException;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A doubly linked list of {@link AbstractInsnNode} objects. <i>This

- * implementation is not thread safe</i>.

- */

-public class InsnList {

-

-    /**

-     * Indicates if preconditions of methods of this class must be checked.

-     * <i>Checking preconditions causes the {@link #indexOf indexOf},

-     * {@link #set set}, {@link #insert(AbstractInsnNode, AbstractInsnNode)},

-     * {@link #insert(AbstractInsnNode, InsnList)}, {@link #remove remove} and

-     * {@link #clear} methods to execute in O(n) time instead of O(1)</i>.

-     */

-    public static boolean check;

-

-    /**

-     * The number of instructions in this list.

-     */

-    private int size;

-

-    /**

-     * The first instruction in this list. May be <tt>null</tt>.

-     */

-    private AbstractInsnNode first;

-

-    /**

-     * The last instruction in this list. May be <tt>null</tt>.

-     */

-    private AbstractInsnNode last;

-

-    /**

-     * A cache of the instructions of this list. This cache is used to improve

-     * the performance of the {@link #get} method.

-     */

-    private AbstractInsnNode[] cache;

-

-    /**

-     * Returns the number of instructions in this list.

-     * 

-     * @return the number of instructions in this list.

-     */

-    public int size() {

-        return size;

-    }

-

-    /**

-     * Returns the first instruction in this list.

-     * 

-     * @return the first instruction in this list, or <tt>null</tt> if the

-     *         list is empty.

-     */

-    public AbstractInsnNode getFirst() {

-        return first;

-    }

-

-    /**

-     * Returns the last instruction in this list.

-     * 

-     * @return the last instruction in this list, or <tt>null</tt> if the list

-     *         is empty.

-     */

-    public AbstractInsnNode getLast() {

-        return last;

-    }

-

-    /**

-     * Returns the instruction whose index is given. This method builds a cache

-     * of the instructions in this list to avoid scanning the whole list each

-     * time it is called. Once the cache is built, this method run in constant

-     * time. This cache is invalidated by all the methods that modify the list.

-     * 

-     * @param index the index of the instruction that must be returned.

-     * @return the instruction whose index is given.

-     * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).

-     */

-    public AbstractInsnNode get(final int index) {

-        if (index < 0 || index >= size) {

-            throw new IndexOutOfBoundsException();

-        }

-        if (cache == null) {

-            cache = toArray();

-        }

-        return cache[index];

-    }

-

-    /**

-     * Returns <tt>true</tt> if the given instruction belongs to this list.

-     * This method always scans the instructions of this list until it finds the

-     * given instruction or reaches the end of the list.

-     * 

-     * @param insn an instruction.

-     * @return <tt>true</tt> if the given instruction belongs to this list.

-     */

-    public boolean contains(final AbstractInsnNode insn) {

-        AbstractInsnNode i = first;

-        while (i != null && i != insn) {

-            i = i.next;

-        }

-        return i != null;

-    }

-

-    /**

-     * Returns the index of the given instruction in this list. This method

-     * builds a cache of the instruction indexes to avoid scanning the whole

-     * list each time it is called. Once the cache is built, this method run in

-     * constant time. The cache is invalidated by all the methods that modify

-     * the list.

-     * 

-     * @param insn an instruction <i>of this list</i>.

-     * @return the index of the given instruction in this list. <i>The result of

-     *         this method is undefined if the given instruction does not belong

-     *         to this list</i>. Use {@link #contains contains} to test if an

-     *         instruction belongs to an instruction list or not.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt> and

-     *         if insn does not belong to this list.

-     */

-    public int indexOf(final AbstractInsnNode insn) {

-        if (check && !contains(insn)) {

-            throw new IllegalArgumentException();

-        }

-        if (cache == null) {

-            cache = toArray();

-        }

-        return insn.index;

-    }

-

-    /**

-     * Makes the given visitor visit all of the instructions in this list.

-     * 

-     * @param mv the method visitor that must visit the instructions.

-     */

-    public void accept(final MethodVisitor mv) {

-        AbstractInsnNode insn = first;

-        while (insn != null) {

-            insn.accept(mv);

-            insn = insn.next;

-        }

-    }

-

-    /**

-     * Returns an iterator over the instructions in this list.

-     * 

-     * @return an iterator over the instructions in this list.

-     */

-    public ListIterator iterator() {

-        return iterator(0);

-    }

-

-    /**

-     * Returns an iterator over the instructions in this list.

-     * 

-     * @return an iterator over the instructions in this list.

-     */

-    public ListIterator iterator(int index) {

-        return new InsnListIterator(index);

-    }

-    

-    /**

-     * Returns an array containing all of the instructions in this list.

-     * 

-     * @return an array containing all of the instructions in this list.

-     */

-    public AbstractInsnNode[] toArray() {

-        int i = 0;

-        AbstractInsnNode elem = first;

-        AbstractInsnNode[] insns = new AbstractInsnNode[size];

-        while (elem != null) {

-            insns[i] = elem;

-            elem.index = i++;

-            elem = elem.next;

-        }

-        return insns;

-    }

-

-    /**

-     * Replaces an instruction of this list with another instruction.

-     * 

-     * @param location an instruction <i>of this list</i>.

-     * @param insn another instruction, <i>which must not belong to any

-     *        {@link InsnList}</i>.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if i does not belong to this list or if insn belongs to an

-     *         instruction list.

-     */

-    public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {

-        if (check && !(contains(location) && insn.index == -1)) {

-            throw new IllegalArgumentException();

-        }

-        AbstractInsnNode next = location.next;

-        insn.next = next;

-        if (next != null) {

-            next.prev = insn;

-        } else {

-            last = insn;

-        }

-        AbstractInsnNode prev = location.prev;

-        insn.prev = prev;

-        if (prev != null) {

-            prev.next = insn;

-        } else {

-            first = insn;

-        }

-        if (cache != null) {

-            int index = location.index;

-            cache[index] = insn;

-            insn.index = index;

-        } else {

-            insn.index = 0; // insn now belongs to an InsnList

-        }

-        location.index = -1; // i no longer belongs to an InsnList

-        location.prev = null;

-        location.next = null;

-    }

-

-    /**

-     * Adds the given instruction to the end of this list.

-     * 

-     * @param insn an instruction, <i>which must not belong to any

-     *        {@link InsnList}</i>.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if insn belongs to an instruction list.

-     */

-    public void add(final AbstractInsnNode insn) {

-        if (check && insn.index != -1) {

-            throw new IllegalArgumentException();

-        }

-        ++size;

-        if (last == null) {

-            first = insn;

-            last = insn;

-        } else {

-            last.next = insn;

-            insn.prev = last;

-        }

-        last = insn;

-        cache = null;

-        insn.index = 0; // insn now belongs to an InsnList

-    }

-

-    /**

-     * Adds the given instructions to the end of this list.

-     * 

-     * @param insns an instruction list, which is cleared during the process.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if insn == this.

-     */

-    public void add(final InsnList insns) {

-        if (check && insns == this) {

-            throw new IllegalArgumentException();

-        }

-        if (insns.size == 0) {

-            return;

-        }

-        size += insns.size;

-        if (last == null) {

-            first = insns.first;

-            last = insns.last;

-        } else {

-            AbstractInsnNode elem = insns.first;

-            last.next = elem;

-            elem.prev = last;

-            last = insns.last;

-        }

-        cache = null;

-        insns.removeAll(false);

-    }

-

-    /**

-     * Inserts the given instruction at the begining of this list.

-     * 

-     * @param insn an instruction, <i>which must not belong to any

-     *        {@link InsnList}</i>.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if insn belongs to an instruction list.

-     */

-    public void insert(final AbstractInsnNode insn) {

-        if (check && insn.index != -1) {

-            throw new IllegalArgumentException();

-        }

-        ++size;

-        if (first == null) {

-            first = insn;

-            last = insn;

-        } else {

-            first.prev = insn;

-            insn.next = first;

-        }

-        first = insn;

-        cache = null;

-        insn.index = 0; // insn now belongs to an InsnList

-    }

-

-    /**

-     * Inserts the given instructions at the begining of this list.

-     * 

-     * @param insns an instruction list, which is cleared during the process.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if insn == this.

-     */

-    public void insert(final InsnList insns) {

-        if (check && insns == this) {

-            throw new IllegalArgumentException();

-        }

-        if (insns.size == 0) {

-            return;

-        }

-        size += insns.size;

-        if (first == null) {

-            first = insns.first;

-            last = insns.last;

-        } else {

-            AbstractInsnNode elem = insns.last;

-            first.prev = elem;

-            elem.next = first;

-            first = insns.first;

-        }

-        cache = null;

-        insns.removeAll(false);

-    }

-

-    /**

-     * Inserts the given instruction after the specified instruction.

-     * 

-     * @param location an instruction <i>of this list</i> after which insn must be

-     *        inserted.

-     * @param insn the instruction to be inserted, <i>which must not belong to

-     *        any {@link InsnList}</i>.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if i does not belong to this list or if insn belongs to an

-     *         instruction list.

-     */

-    public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {

-        if (check && !(contains(location) && insn.index == -1)) {

-            throw new IllegalArgumentException();

-        }

-        ++size;

-        AbstractInsnNode next = location.next;

-        if (next == null) {

-            last = insn;

-        } else {

-            next.prev = insn;

-        }

-        location.next = insn;

-        insn.next = next;

-        insn.prev = location;

-        cache = null;

-        insn.index = 0; // insn now belongs to an InsnList

-    }

-

-    /**

-     * Inserts the given instructions after the specified instruction.

-     * 

-     * @param location an instruction <i>of this list</i> after which the instructions

-     *        must be inserted.

-     * @param insns the instruction list to be inserted, which is cleared during

-     *        the process.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if i does not belong to this list or if insns == this.

-     */

-    public void insert(final AbstractInsnNode location, final InsnList insns) {

-        if (check && !(contains(location) && insns != this)) {

-            throw new IllegalArgumentException();

-        }

-        if (insns.size == 0) {

-            return;

-        }

-        size += insns.size;

-        AbstractInsnNode ifirst = insns.first;

-        AbstractInsnNode ilast = insns.last;

-        AbstractInsnNode next = location.next;

-        if (next == null) {

-            last = ilast;

-        } else {

-            next.prev = ilast;

-        }

-        location.next = ifirst;

-        ilast.next = next;

-        ifirst.prev = location;

-        cache = null;

-        insns.removeAll(false);

-    }

-    

-    /**

-     * Inserts the given instruction before the specified instruction.

-     * 

-     * @param location an instruction <i>of this list</i> before which insn must be

-     *        inserted.

-     * @param insn the instruction to be inserted, <i>which must not belong to

-     *        any {@link InsnList}</i>.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if i does not belong to this list or if insn belongs to an

-     *         instruction list.

-     */

-    public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {

-        if (check && !(contains(location) && insn.index == -1)) {

-            throw new IllegalArgumentException();

-        }

-        ++size;

-        AbstractInsnNode prev = location.prev;

-        if (prev == null) {

-            first = insn;

-        } else {

-            prev.next = insn;

-        }

-        location.prev = insn;

-        insn.next = location;

-        insn.prev = prev;

-        cache = null;

-        insn.index = 0; // insn now belongs to an InsnList

-    }

-    

-    /**

-     * Inserts the given instructions before the specified instruction.

-     * 

-     * @param location  an instruction <i>of this list</i> before which the instructions

-     *        must be inserted.

-     * @param insns the instruction list to be inserted, which is cleared during

-     *        the process.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if i does not belong to this list or if insns == this.

-     */

-    public void insertBefore(final AbstractInsnNode location, final InsnList insns) {

-        if (check && !(contains(location ) && insns != this)) {

-            throw new IllegalArgumentException();

-        }

-        if (insns.size == 0) {

-            return;

-        }

-        size += insns.size;

-        AbstractInsnNode ifirst = insns.first;

-        AbstractInsnNode ilast = insns.last;

-        AbstractInsnNode prev = location .prev;

-        if (prev == null) {

-            first = ifirst;

-        } else {

-            prev.next = ifirst;

-        }

-        location .prev = ilast;

-        ilast.next = location ;

-        ifirst.prev = prev;

-        cache = null;

-        insns.removeAll(false);

-    }

-    

-    

-

-    /**

-     * Removes the given instruction from this list.

-     * 

-     * @param insn the instruction <i>of this list</i> that must be removed.

-     * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,

-     *         and if insn does not belong to this list.

-     */

-    public void remove(final AbstractInsnNode insn) {

-        if (check && !contains(insn)) {

-            throw new IllegalArgumentException();

-        }

-        --size;

-        AbstractInsnNode next = insn.next;

-        AbstractInsnNode prev = insn.prev;

-        if (next == null) {

-            if (prev == null) {

-                first = null;

-                last = null;

-            } else {

-                prev.next = null;

-                last = prev;

-            }

-        } else {

-            if (prev == null) {

-                first = next;

-                next.prev = null;

-            } else {

-                prev.next = next;

-                next.prev = prev;

-            }

-        }

-        cache = null;

-        insn.index = -1; // insn no longer belongs to an InsnList

-        insn.prev = null;

-        insn.next = null;

-    }

-

-    /**

-     * Removes all of the instructions of this list.

-     * 

-     * @param mark if the instructions must be marked as no longer belonging to

-     *        any {@link InsnList}.

-     */

-    private void removeAll(final boolean mark) {

-        if (mark) {

-            AbstractInsnNode insn = first;

-            while (insn != null) {

-                AbstractInsnNode next = insn.next;

-                insn.index = -1; // insn no longer belongs to an InsnList

-                insn.prev = null;

-                insn.next = null;

-                insn = next;

-            }

-        }

-        size = 0;

-        first = null;

-        last = null;

-        cache = null;

-    }

-

-    /**

-     * Removes all of the instructions of this list.

-     */

-    public void clear() {

-        removeAll(check);

-    }

-

-    /**

-     * Reset all labels in the instruction list. This method should be called

-     * before reusing same instructions list between several

-     * <code>ClassWriter</code>s.

-     */

-    public void resetLabels() {

-        AbstractInsnNode insn = first;

-        while (insn != null) {

-            if (insn instanceof LabelNode) {

-                ((LabelNode) insn).resetLabel();

-            }

-            insn = insn.next;

-        }

-    }

-    

-    private final class InsnListIterator implements ListIterator {

-        AbstractInsnNode next;

-        AbstractInsnNode prev;

-

-        private InsnListIterator(int index) {

-            if(index==size()) {

-                next = null;

-                prev = getLast();

-            } else {

-                next = get(index);

-                prev = next.prev;

-            }

-        }

-

-        public boolean hasNext() {

-            return next != null;

-        }

-

-        public Object next() {

-            if (next == null) {

-                throw new NoSuchElementException();

-            }

-            AbstractInsnNode result = next;

-            prev = result;

-            next = result.next;

-            return result;

-        }

-

-        public void remove() {

-            InsnList.this.remove(prev);

-            prev = prev.prev;

-        }

-

-        public boolean hasPrevious() {

-            return prev != null;

-        }

-

-        public Object previous() {

-            AbstractInsnNode result = prev;

-            next = result;

-            prev = result.prev;

-            return result;

-        }

-

-        public int nextIndex() {

-            if (next == null) {

-                return size();

-            }

-            if (cache == null) {

-                cache = toArray();

-            }

-            return next.index;

-        }

-

-        public int previousIndex() {

-            if (prev == null) {

-                return -1;

-            }

-            if (cache == null) {

-                cache = toArray();

-            }

-            return prev.index;

-        }

-

-        public void add(Object o) {

-            InsnList.this.insertBefore(next, (AbstractInsnNode) o);

-            prev = (AbstractInsnNode) o;

-        }

-

-        public void set(Object o) {

-            InsnList.this.set(next.prev, (AbstractInsnNode) o);

-            prev = (AbstractInsnNode) o;

-        }

-    }

-

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/InsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/InsnNode.java
deleted file mode 100644
index eda7eb2..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/InsnNode.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a zero operand instruction.

- * 

- * @author Eric Bruneton

- */

-public class InsnNode extends AbstractInsnNode {

-

-    /**

-     * Constructs a new {@link InsnNode}.

-     * 

-     * @param opcode the opcode of the instruction to be constructed. This

-     *        opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,

-     *        ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,

-     *        FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,

-     *        FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE,

-     *        FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2,

-     *        DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD,

-     *        FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,

-     *        LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG,

-     *        ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR,

-     *        LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,

-     *        I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,

-     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,

-     *        MONITORENTER, or MONITOREXIT.

-     */

-    public InsnNode(final int opcode) {

-        super(opcode);

-    }

-

-    public int getType() {

-        return INSN;

-    }

-

-    /**

-     * Makes the given visitor visit this instruction.

-     * 

-     * @param mv a method visitor.

-     */

-    public void accept(final MethodVisitor mv) {

-        mv.visitInsn(opcode);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new InsnNode(opcode);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/IntInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/IntInsnNode.java
deleted file mode 100644
index 8578583..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/IntInsnNode.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents an instruction with a single int operand.

- * 

- * @author Eric Bruneton

- */

-public class IntInsnNode extends AbstractInsnNode {

-

-    /**

-     * The operand of this instruction.

-     */

-    public int operand;

-

-    /**

-     * Constructs a new {@link IntInsnNode}.

-     * 

-     * @param opcode the opcode of the instruction to be constructed. This

-     *        opcode must be BIPUSH, SIPUSH or NEWARRAY.

-     * @param operand the operand of the instruction to be constructed.

-     */

-    public IntInsnNode(final int opcode, final int operand) {

-        super(opcode);

-        this.operand = operand;

-    }

-

-    /**

-     * Sets the opcode of this instruction.

-     * 

-     * @param opcode the new instruction opcode. This opcode must be BIPUSH,

-     *        SIPUSH or NEWARRAY.

-     */

-    public void setOpcode(final int opcode) {

-        this.opcode = opcode;

-    }

-

-    public int getType() {

-        return INT_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitIntInsn(opcode, operand);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new IntInsnNode(opcode, operand);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/JumpInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/JumpInsnNode.java
deleted file mode 100644
index efc94a7..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/JumpInsnNode.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a jump instruction. A jump instruction is an

- * instruction that may jump to another instruction.

- * 

- * @author Eric Bruneton

- */

-public class JumpInsnNode extends AbstractInsnNode {

-

-    /**

-     * The operand of this instruction. This operand is a label that designates

-     * the instruction to which this instruction may jump.

-     */

-    public LabelNode label;

-

-    /**

-     * Constructs a new {@link JumpInsnNode}.

-     * 

-     * @param opcode the opcode of the type instruction to be constructed. This

-     *        opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,

-     *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,

-     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.

-     * @param label the operand of the instruction to be constructed. This

-     *        operand is a label that designates the instruction to which the

-     *        jump instruction may jump.

-     */

-    public JumpInsnNode(final int opcode, final LabelNode label) {

-        super(opcode);

-        this.label = label;

-    }

-

-    /**

-     * Sets the opcode of this instruction.

-     * 

-     * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,

-     *        IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,

-     *        IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,

-     *        IFNULL or IFNONNULL.

-     */

-    public void setOpcode(final int opcode) {

-        this.opcode = opcode;

-    }

-

-    public int getType() {

-        return JUMP_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitJumpInsn(opcode, label.getLabel());

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new JumpInsnNode(opcode, clone(label, labels));

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/LabelNode.java b/cglib-and-asm/src/org/mockito/asm/tree/LabelNode.java
deleted file mode 100644
index 001f218..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/LabelNode.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodVisitor;

-

-/**

- * An {@link AbstractInsnNode} that encapsulates a {@link Label}.

- */

-public class LabelNode extends AbstractInsnNode {

-

-    private Label label;

-

-    public LabelNode() {

-        super(-1);

-    }

-

-    public LabelNode(final Label label) {

-        super(-1);

-        this.label = label;

-    }

-

-    public int getType() {

-        return LABEL;

-    }

-

-    public Label getLabel() {

-        if (label == null) {

-            label = new Label();

-        }

-        return label;

-    }

-

-    public void accept(final MethodVisitor cv) {

-        cv.visitLabel(getLabel());

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return (LabelNode) labels.get(this);

-    }

-

-    public void resetLabel() {

-        label = null;

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/LdcInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/LdcInsnNode.java
deleted file mode 100644
index b960448..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/LdcInsnNode.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-/**

- * A node that represents an LDC instruction.

- * 

- * @author Eric Bruneton

- */

-public class LdcInsnNode extends AbstractInsnNode {

-

-    /**

-     * The constant to be loaded on the stack. This parameter must be a non null

-     * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a

-     * {@link String} or a {@link org.mockito.asm.Type}.

-     */

-    public Object cst;

-

-    /**

-     * Constructs a new {@link LdcInsnNode}.

-     * 

-     * @param cst the constant to be loaded on the stack. This parameter must be

-     *        a non null {@link Integer}, a {@link Float}, a {@link Long}, a

-     *        {@link Double} or a {@link String}.

-     */

-    public LdcInsnNode(final Object cst) {

-        super(Opcodes.LDC);

-        this.cst = cst;

-    }

-

-    public int getType() {

-        return LDC_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitLdcInsn(cst);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new LdcInsnNode(cst);

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/LineNumberNode.java b/cglib-and-asm/src/org/mockito/asm/tree/LineNumberNode.java
deleted file mode 100644
index 8b1ac86..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/LineNumberNode.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a line number declaration. These nodes are pseudo

- * instruction nodes in order to be inserted in an instruction list.

- * 

- * @author Eric Bruneton

- */

-public class LineNumberNode extends AbstractInsnNode {

-

-    /**

-     * A line number. This number refers to the source file from which the class

-     * was compiled.

-     */

-    public int line;

-

-    /**

-     * The first instruction corresponding to this line number.

-     */

-    public LabelNode start;

-

-    /**

-     * Constructs a new {@link LineNumberNode}.

-     * 

-     * @param line a line number. This number refers to the source file from

-     *        which the class was compiled.

-     * @param start the first instruction corresponding to this line number.

-     */

-    public LineNumberNode(final int line, final LabelNode start) {

-        super(-1);

-        this.line = line;

-        this.start = start;

-    }

-

-    public int getType() {

-        return LINE;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitLineNumber(line, start.getLabel());

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new LineNumberNode(line, clone(start, labels));

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/LocalVariableNode.java b/cglib-and-asm/src/org/mockito/asm/tree/LocalVariableNode.java
deleted file mode 100644
index f45898e..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/LocalVariableNode.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a local variable declaration.

- * 

- * @author Eric Bruneton

- */

-public class LocalVariableNode {

-

-    /**

-     * The name of a local variable.

-     */

-    public String name;

-

-    /**

-     * The type descriptor of this local variable.

-     */

-    public String desc;

-

-    /**

-     * The signature of this local variable. May be <tt>null</tt>.

-     */

-    public String signature;

-

-    /**

-     * The first instruction corresponding to the scope of this local variable

-     * (inclusive).

-     */

-    public LabelNode start;

-

-    /**

-     * The last instruction corresponding to the scope of this local variable

-     * (exclusive).

-     */

-    public LabelNode end;

-

-    /**

-     * The local variable's index.

-     */

-    public int index;

-

-    /**

-     * Constructs a new {@link LocalVariableNode}.

-     * 

-     * @param name the name of a local variable.

-     * @param desc the type descriptor of this local variable.

-     * @param signature the signature of this local variable. May be

-     *        <tt>null</tt>.

-     * @param start the first instruction corresponding to the scope of this

-     *        local variable (inclusive).

-     * @param end the last instruction corresponding to the scope of this local

-     *        variable (exclusive).

-     * @param index the local variable's index.

-     */

-    public LocalVariableNode(

-        final String name,

-        final String desc,

-        final String signature,

-        final LabelNode start,

-        final LabelNode end,

-        final int index)

-    {

-        this.name = name;

-        this.desc = desc;

-        this.signature = signature;

-        this.start = start;

-        this.end = end;

-        this.index = index;

-    }

-

-    /**

-     * Makes the given visitor visit this local variable declaration.

-     * 

-     * @param mv a method visitor.

-     */

-    public void accept(final MethodVisitor mv) {

-        mv.visitLocalVariable(name,

-                desc,

-                signature,

-                start.getLabel(),

-                end.getLabel(),

-                index);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/LookupSwitchInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/LookupSwitchInsnNode.java
deleted file mode 100644
index 809b764..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/LookupSwitchInsnNode.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-import java.util.List;

-import java.util.ArrayList;

-import java.util.Arrays;

-import java.util.Map;

-

-/**

- * A node that represents a LOOKUPSWITCH instruction.

- * 

- * @author Eric Bruneton

- */

-public class LookupSwitchInsnNode extends AbstractInsnNode {

-

-    /**

-     * Beginning of the default handler block.

-     */

-    public LabelNode dflt;

-

-    /**

-     * The values of the keys. This list is a list of {@link Integer} objects.

-     */

-    public List keys;

-

-    /**

-     * Beginnings of the handler blocks. This list is a list of

-     * {@link LabelNode} objects.

-     */

-    public List labels;

-

-    /**

-     * Constructs a new {@link LookupSwitchInsnNode}.

-     * 

-     * @param dflt beginning of the default handler block.

-     * @param keys the values of the keys.

-     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is

-     *        the beginning of the handler block for the <tt>keys[i]</tt> key.

-     */

-    public LookupSwitchInsnNode(

-        final LabelNode dflt,

-        final int[] keys,

-        final LabelNode[] labels)

-    {

-        super(Opcodes.LOOKUPSWITCH);

-        this.dflt = dflt;

-        this.keys = new ArrayList(keys == null ? 0 : keys.length);

-        this.labels = new ArrayList(labels == null ? 0 : labels.length);

-        if (keys != null) {

-            for (int i = 0; i < keys.length; ++i) {

-                this.keys.add(new Integer(keys[i]));

-            }

-        }

-        if (labels != null) {

-            this.labels.addAll(Arrays.asList(labels));

-        }

-    }

-

-    public int getType() {

-        return LOOKUPSWITCH_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        int[] keys = new int[this.keys.size()];

-        for (int i = 0; i < keys.length; ++i) {

-            keys[i] = ((Integer) this.keys.get(i)).intValue();

-        }

-        Label[] labels = new Label[this.labels.size()];

-        for (int i = 0; i < labels.length; ++i) {

-            labels[i] = ((LabelNode) this.labels.get(i)).getLabel();

-        }

-        mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,

-                labels), null, clone(this.labels, labels));

-        clone.keys.addAll(keys);

-        return clone;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/MemberNode.java b/cglib-and-asm/src/org/mockito/asm/tree/MemberNode.java
deleted file mode 100644
index 501efe7..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/MemberNode.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.ArrayList;

-import java.util.List;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-

-/**

- * An abstract class, field or method node.

- * 

- * @author Eric Bruneton

- */

-public abstract class MemberNode {

-

-    /**

-     * The runtime visible annotations of this class, field or method. This list

-     * is a list of {@link AnnotationNode} objects. May be <tt>null</tt>.

-     * 

-     * @associates org.mockito.asm.tree.AnnotationNode

-     * @label visible

-     */

-    public List visibleAnnotations;

-

-    /**

-     * The runtime invisible annotations of this class, field or method. This

-     * list is a list of {@link AnnotationNode} objects. May be <tt>null</tt>.

-     * 

-     * @associates org.mockito.asm.tree.AnnotationNode

-     * @label invisible

-     */

-    public List invisibleAnnotations;

-

-    /**

-     * The non standard attributes of this class, field or method. This list is

-     * a list of {@link Attribute} objects. May be <tt>null</tt>.

-     * 

-     * @associates org.mockito.asm.Attribute

-     */

-    public List attrs;

-

-    /**

-     * Constructs a new {@link MemberNode}.

-     */

-    protected MemberNode() {

-    }

-

-    /**

-     * Visits an annotation of this class, field or method.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values.

-     */

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        AnnotationNode an = new AnnotationNode(desc);

-        if (visible) {

-            if (visibleAnnotations == null) {

-                visibleAnnotations = new ArrayList(1);

-            }

-            visibleAnnotations.add(an);

-        } else {

-            if (invisibleAnnotations == null) {

-                invisibleAnnotations = new ArrayList(1);

-            }

-            invisibleAnnotations.add(an);

-        }

-        return an;

-    }

-

-    /**

-     * Visits a non standard attribute of this class, field or method.

-     * 

-     * @param attr an attribute.

-     */

-    public void visitAttribute(final Attribute attr) {

-        if (attrs == null) {

-            attrs = new ArrayList(1);

-        }

-        attrs.add(attr);

-    }

-

-    /**

-     * Visits the end of this class, field or method.

-     */

-    public void visitEnd() {

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/MethodInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/MethodInsnNode.java
deleted file mode 100644
index 68b4499..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/MethodInsnNode.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a method instruction. A method instruction is an

- * instruction that invokes a method.

- * 

- * @author Eric Bruneton

- */

-public class MethodInsnNode extends AbstractInsnNode {

-

-    /**

-     * The internal name of the method's owner class (see

-     * {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     */

-    public String owner;

-

-    /**

-     * The method's name.

-     */

-    public String name;

-

-    /**

-     * The method's descriptor (see {@link org.mockito.asm.Type}).

-     */

-    public String desc;

-

-    /**

-     * Constructs a new {@link MethodInsnNode}.

-     * 

-     * @param opcode the opcode of the type instruction to be constructed. This

-     *        opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or

-     *        INVOKEINTERFACE.

-     * @param owner the internal name of the method's owner class (see

-     *        {@link org.mockito.asm.Type#getInternalName() getInternalName}).

-     * @param name the method's name.

-     * @param desc the method's descriptor (see {@link org.mockito.asm.Type}).

-     */

-    public MethodInsnNode(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        super(opcode);

-        this.owner = owner;

-        this.name = name;

-        this.desc = desc;

-    }

-

-    /**

-     * Sets the opcode of this instruction.

-     * 

-     * @param opcode the new instruction opcode. This opcode must be

-     *        INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.

-     */

-    public void setOpcode(final int opcode) {

-        this.opcode = opcode;

-    }

-

-    public int getType() {

-        return METHOD_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitMethodInsn(opcode, owner, name, desc);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new MethodInsnNode(opcode, owner, name, desc);

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/MethodNode.java b/cglib-and-asm/src/org/mockito/asm/tree/MethodNode.java
deleted file mode 100644
index 11a17e8..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/MethodNode.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.ClassVisitor;

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-

-import java.util.List;

-import java.util.ArrayList;

-import java.util.Arrays;

-

-/**

- * A node that represents a method.

- * 

- * @author Eric Bruneton

- */

-public class MethodNode extends MemberNode implements MethodVisitor {

-

-    /**

-     * The method's access flags (see {@link Opcodes}). This field also

-     * indicates if the method is synthetic and/or deprecated.

-     */

-    public int access;

-

-    /**

-     * The method's name.

-     */

-    public String name;

-

-    /**

-     * The method's descriptor (see {@link Type}).

-     */

-    public String desc;

-

-    /**

-     * The method's signature. May be <tt>null</tt>.

-     */

-    public String signature;

-

-    /**

-     * The internal names of the method's exception classes (see

-     * {@link Type#getInternalName() getInternalName}). This list is a list of

-     * {@link String} objects.

-     */

-    public List exceptions;

-

-    /**

-     * The default value of this annotation interface method. This field must be

-     * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},

-     * {@link Integer}, {@link Long}, {@link Float}, {@link Double},

-     * {@link String} or {@link Type}, or an two elements String array (for

-     * enumeration values), a {@link AnnotationNode}, or a {@link List} of

-     * values of one of the preceding types. May be <tt>null</tt>.

-     */

-    public Object annotationDefault;

-

-    /**

-     * The runtime visible parameter annotations of this method. These lists are

-     * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.

-     * 

-     * @associates org.mockito.asm.tree.AnnotationNode

-     * @label invisible parameters

-     */

-    public List[] visibleParameterAnnotations;

-

-    /**

-     * The runtime invisible parameter annotations of this method. These lists

-     * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.

-     * 

-     * @associates org.mockito.asm.tree.AnnotationNode

-     * @label visible parameters

-     */

-    public List[] invisibleParameterAnnotations;

-

-    /**

-     * The instructions of this method. This list is a list of

-     * {@link AbstractInsnNode} objects.

-     * 

-     * @associates org.mockito.asm.tree.AbstractInsnNode

-     * @label instructions

-     */

-    public InsnList instructions;

-

-    /**

-     * The try catch blocks of this method. This list is a list of

-     * {@link TryCatchBlockNode} objects.

-     * 

-     * @associates org.mockito.asm.tree.TryCatchBlockNode

-     */

-    public List tryCatchBlocks;

-

-    /**

-     * The maximum stack size of this method.

-     */

-    public int maxStack;

-

-    /**

-     * The maximum number of local variables of this method.

-     */

-    public int maxLocals;

-

-    /**

-     * The local variables of this method. This list is a list of

-     * {@link LocalVariableNode} objects. May be <tt>null</tt>

-     * 

-     * @associates org.mockito.asm.tree.LocalVariableNode

-     */

-    public List localVariables;

-

-    /**

-     * Constructs an unitialized {@link MethodNode}.

-     */

-    public MethodNode() {

-        this.instructions = new InsnList();

-    }

-    

-    /**

-     * Constructs a new {@link MethodNode}.

-     * 

-     * @param access the method's access flags (see {@link Opcodes}). This

-     *        parameter also indicates if the method is synthetic and/or

-     *        deprecated.

-     * @param name the method's name.

-     * @param desc the method's descriptor (see {@link Type}).

-     * @param signature the method's signature. May be <tt>null</tt>.

-     * @param exceptions the internal names of the method's exception classes

-     *        (see {@link Type#getInternalName() getInternalName}). May be

-     *        <tt>null</tt>.

-     */

-    public MethodNode(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        this();

-        this.access = access;

-        this.name = name;

-        this.desc = desc;

-        this.signature = signature;

-        this.exceptions = new ArrayList(exceptions == null

-                ? 0

-                : exceptions.length);

-        boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;

-        if (!isAbstract) {

-            this.localVariables = new ArrayList(5);

-        }

-        this.tryCatchBlocks = new ArrayList();

-        if (exceptions != null) {

-            this.exceptions.addAll(Arrays.asList(exceptions));

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the MethodVisitor interface

-    // ------------------------------------------------------------------------

-

-    public AnnotationVisitor visitAnnotationDefault() {

-        return new AnnotationNode(new ArrayList(0) {

-            public boolean add(final Object o) {

-                annotationDefault = o;

-                return super.add(o);

-            }

-        });

-    }

-

-    public AnnotationVisitor visitParameterAnnotation(

-        final int parameter,

-        final String desc,

-        final boolean visible)

-    {

-        AnnotationNode an = new AnnotationNode(desc);

-        if (visible) {

-            if (visibleParameterAnnotations == null) {

-                int params = Type.getArgumentTypes(this.desc).length;

-                visibleParameterAnnotations = new List[params];

-            }

-            if (visibleParameterAnnotations[parameter] == null) {

-                visibleParameterAnnotations[parameter] = new ArrayList(1);

-            }

-            visibleParameterAnnotations[parameter].add(an);

-        } else {

-            if (invisibleParameterAnnotations == null) {

-                int params = Type.getArgumentTypes(this.desc).length;

-                invisibleParameterAnnotations = new List[params];

-            }

-            if (invisibleParameterAnnotations[parameter] == null) {

-                invisibleParameterAnnotations[parameter] = new ArrayList(1);

-            }

-            invisibleParameterAnnotations[parameter].add(an);

-        }

-        return an;

-    }

-

-    public void visitCode() {

-    }

-

-    public void visitFrame(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        instructions.add(new FrameNode(type, nLocal, local == null

-                ? null

-                : getLabelNodes(local), nStack, stack == null

-                ? null

-                : getLabelNodes(stack)));

-    }

-

-    public void visitInsn(final int opcode) {

-        instructions.add(new InsnNode(opcode));

-    }

-

-    public void visitIntInsn(final int opcode, final int operand) {

-        instructions.add(new IntInsnNode(opcode, operand));

-    }

-

-    public void visitVarInsn(final int opcode, final int var) {

-        instructions.add(new VarInsnNode(opcode, var));

-    }

-

-    public void visitTypeInsn(final int opcode, final String type) {

-        instructions.add(new TypeInsnNode(opcode, type));

-    }

-

-    public void visitFieldInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        instructions.add(new FieldInsnNode(opcode, owner, name, desc));

-    }

-

-    public void visitMethodInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        instructions.add(new MethodInsnNode(opcode, owner, name, desc));

-    }

-

-    public void visitJumpInsn(final int opcode, final Label label) {

-        instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));

-    }

-

-    public void visitLabel(final Label label) {

-        instructions.add(getLabelNode(label));

-    }

-

-    public void visitLdcInsn(final Object cst) {

-        instructions.add(new LdcInsnNode(cst));

-    }

-

-    public void visitIincInsn(final int var, final int increment) {

-        instructions.add(new IincInsnNode(var, increment));

-    }

-

-    public void visitTableSwitchInsn(

-        final int min,

-        final int max,

-        final Label dflt,

-        final Label[] labels)

-    {

-        instructions.add(new TableSwitchInsnNode(min,

-                max,

-                getLabelNode(dflt),

-                getLabelNodes(labels)));

-    }

-

-    public void visitLookupSwitchInsn(

-        final Label dflt,

-        final int[] keys,

-        final Label[] labels)

-    {

-        instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),

-                keys,

-                getLabelNodes(labels)));

-    }

-

-    public void visitMultiANewArrayInsn(final String desc, final int dims) {

-        instructions.add(new MultiANewArrayInsnNode(desc, dims));

-    }

-

-    public void visitTryCatchBlock(

-        final Label start,

-        final Label end,

-        final Label handler,

-        final String type)

-    {

-        tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),

-                getLabelNode(end),

-                getLabelNode(handler),

-                type));

-    }

-

-    public void visitLocalVariable(

-        final String name,

-        final String desc,

-        final String signature,

-        final Label start,

-        final Label end,

-        final int index)

-    {

-        localVariables.add(new LocalVariableNode(name,

-                desc,

-                signature,

-                getLabelNode(start),

-                getLabelNode(end),

-                index));

-    }

-

-    public void visitLineNumber(final int line, final Label start) {

-        instructions.add(new LineNumberNode(line, getLabelNode(start)));

-    }

-

-    public void visitMaxs(final int maxStack, final int maxLocals) {

-        this.maxStack = maxStack;

-        this.maxLocals = maxLocals;

-    }

-

-    /**

-     * Returns the LabelNode corresponding to the given Label. Creates a new 

-     * LabelNode if necessary. The default implementation of this method uses

-     * the {@link Label#info} field to store associations between labels and

-     * label nodes.

-     * 

-     * @param l a Label.

-     * @return the LabelNode corresponding to l.

-     */    

-    protected LabelNode getLabelNode(final Label l) {

-        if (!(l.info instanceof LabelNode)) {

-            l.info = new LabelNode(l);

-        }

-        return (LabelNode) l.info;

-    }

-

-    private LabelNode[] getLabelNodes(final Label[] l) {

-        LabelNode[] nodes = new LabelNode[l.length];

-        for (int i = 0; i < l.length; ++i) {

-            nodes[i] = getLabelNode(l[i]);

-        }

-        return nodes;

-    }

-

-    private Object[] getLabelNodes(final Object[] objs) {

-        Object[] nodes = new Object[objs.length];

-        for (int i = 0; i < objs.length; ++i) {

-            Object o = objs[i];

-            if (o instanceof Label) {

-                o = getLabelNode((Label) o);

-            }

-            nodes[i] = o;

-        }

-        return nodes;

-    }

-

-    // ------------------------------------------------------------------------

-    // Accept method

-    // ------------------------------------------------------------------------

-

-    /**

-     * Makes the given class visitor visit this method.

-     * 

-     * @param cv a class visitor.

-     */

-    public void accept(final ClassVisitor cv) {

-        String[] exceptions = new String[this.exceptions.size()];

-        this.exceptions.toArray(exceptions);

-        MethodVisitor mv = cv.visitMethod(access,

-                name,

-                desc,

-                signature,

-                exceptions);

-        if (mv != null) {

-            accept(mv);

-        }

-    }

-

-    /**

-     * Makes the given method visitor visit this method.

-     * 

-     * @param mv a method visitor.

-     */

-    public void accept(final MethodVisitor mv) {

-        // visits the method attributes

-        int i, j, n;

-        if (annotationDefault != null) {

-            AnnotationVisitor av = mv.visitAnnotationDefault();

-            AnnotationNode.accept(av, null, annotationDefault);

-            if (av != null) {

-                av.visitEnd();

-            }

-        }

-        n = visibleAnnotations == null ? 0 : visibleAnnotations.size();

-        for (i = 0; i < n; ++i) {

-            AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);

-            an.accept(mv.visitAnnotation(an.desc, true));

-        }

-        n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();

-        for (i = 0; i < n; ++i) {

-            AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);

-            an.accept(mv.visitAnnotation(an.desc, false));

-        }

-        n = visibleParameterAnnotations == null

-                ? 0

-                : visibleParameterAnnotations.length;

-        for (i = 0; i < n; ++i) {

-            List l = visibleParameterAnnotations[i];

-            if (l == null) {

-                continue;

-            }

-            for (j = 0; j < l.size(); ++j) {

-                AnnotationNode an = (AnnotationNode) l.get(j);

-                an.accept(mv.visitParameterAnnotation(i, an.desc, true));

-            }

-        }

-        n = invisibleParameterAnnotations == null

-                ? 0

-                : invisibleParameterAnnotations.length;

-        for (i = 0; i < n; ++i) {

-            List l = invisibleParameterAnnotations[i];

-            if (l == null) {

-                continue;

-            }

-            for (j = 0; j < l.size(); ++j) {

-                AnnotationNode an = (AnnotationNode) l.get(j);

-                an.accept(mv.visitParameterAnnotation(i, an.desc, false));

-            }

-        }

-        n = attrs == null ? 0 : attrs.size();

-        for (i = 0; i < n; ++i) {

-            mv.visitAttribute((Attribute) attrs.get(i));

-        }

-        // visits the method's code

-        if (instructions.size() > 0) {

-            mv.visitCode();

-            // visits try catch blocks

-            for (i = 0; i < tryCatchBlocks.size(); ++i) {

-                ((TryCatchBlockNode) tryCatchBlocks.get(i)).accept(mv);

-            }

-            // visits instructions

-            instructions.accept(mv);

-            // visits local variables

-            n = localVariables == null ? 0 : localVariables.size();

-            for (i = 0; i < n; ++i) {

-                ((LocalVariableNode) localVariables.get(i)).accept(mv);

-            }

-            // visits maxs

-            mv.visitMaxs(maxStack, maxLocals);

-        }

-        mv.visitEnd();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/MultiANewArrayInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/MultiANewArrayInsnNode.java
deleted file mode 100644
index efc9dc1..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/MultiANewArrayInsnNode.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-/**

- * A node that represents a MULTIANEWARRAY instruction.

- * 

- * @author Eric Bruneton

- */

-public class MultiANewArrayInsnNode extends AbstractInsnNode {

-

-    /**

-     * An array type descriptor (see {@link org.mockito.asm.Type}).

-     */

-    public String desc;

-

-    /**

-     * Number of dimensions of the array to allocate.

-     */

-    public int dims;

-

-    /**

-     * Constructs a new {@link MultiANewArrayInsnNode}.

-     * 

-     * @param desc an array type descriptor (see {@link org.mockito.asm.Type}).

-     * @param dims number of dimensions of the array to allocate.

-     */

-    public MultiANewArrayInsnNode(final String desc, final int dims) {

-        super(Opcodes.MULTIANEWARRAY);

-        this.desc = desc;

-        this.dims = dims;

-    }

-

-    public int getType() {

-        return MULTIANEWARRAY_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitMultiANewArrayInsn(desc, dims);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new MultiANewArrayInsnNode(desc, dims);

-    }

-

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/TableSwitchInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/TableSwitchInsnNode.java
deleted file mode 100644
index fe038b4..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/TableSwitchInsnNode.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-import java.util.ArrayList;

-import java.util.Arrays;

-import java.util.List;

-import java.util.Map;

-

-/**

- * A node that represents a TABLESWITCH instruction.

- * 

- * @author Eric Bruneton

- */

-public class TableSwitchInsnNode extends AbstractInsnNode {

-

-    /**

-     * The minimum key value.

-     */

-    public int min;

-

-    /**

-     * The maximum key value.

-     */

-    public int max;

-

-    /**

-     * Beginning of the default handler block.

-     */

-    public LabelNode dflt;

-

-    /**

-     * Beginnings of the handler blocks. This list is a list of

-     * {@link LabelNode} objects.

-     */

-    public List labels;

-

-    /**

-     * Constructs a new {@link TableSwitchInsnNode}.

-     * 

-     * @param min the minimum key value.

-     * @param max the maximum key value.

-     * @param dflt beginning of the default handler block.

-     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is

-     *        the beginning of the handler block for the <tt>min + i</tt> key.

-     */

-    public TableSwitchInsnNode(

-        final int min,

-        final int max,

-        final LabelNode dflt,

-        final LabelNode[] labels)

-    {

-        super(Opcodes.TABLESWITCH);

-        this.min = min;

-        this.max = max;

-        this.dflt = dflt;

-        this.labels = new ArrayList();

-        if (labels != null) {

-            this.labels.addAll(Arrays.asList(labels));

-        }

-    }

-

-    public int getType() {

-        return TABLESWITCH_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        Label[] labels = new Label[this.labels.size()];

-        for (int i = 0; i < labels.length; ++i) {

-            labels[i] = ((LabelNode) this.labels.get(i)).getLabel();

-        }

-        mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new TableSwitchInsnNode(min,

-                max,

-                clone(dflt, labels),

-                clone(this.labels, labels));

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/TryCatchBlockNode.java b/cglib-and-asm/src/org/mockito/asm/tree/TryCatchBlockNode.java
deleted file mode 100644
index 8d23f14..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/TryCatchBlockNode.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a try catch block.

- * 

- * @author Eric Bruneton

- */

-public class TryCatchBlockNode {

-

-    /**

-     * Beginning of the exception handler's scope (inclusive).

-     */

-    public LabelNode start;

-

-    /**

-     * End of the exception handler's scope (exclusive).

-     */

-    public LabelNode end;

-

-    /**

-     * Beginning of the exception handler's code.

-     */

-    public LabelNode handler;

-

-    /**

-     * Internal name of the type of exceptions handled by the handler. May be

-     * <tt>null</tt> to catch any exceptions (for "finally" blocks).

-     */

-    public String type;

-

-    /**

-     * Constructs a new {@link TryCatchBlockNode}.

-     * 

-     * @param start beginning of the exception handler's scope (inclusive).

-     * @param end end of the exception handler's scope (exclusive).

-     * @param handler beginning of the exception handler's code.

-     * @param type internal name of the type of exceptions handled by the

-     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"

-     *        blocks).

-     */

-    public TryCatchBlockNode(

-        final LabelNode start,

-        final LabelNode end,

-        final LabelNode handler,

-        final String type)

-    {

-        this.start = start;

-        this.end = end;

-        this.handler = handler;

-        this.type = type;

-    }

-

-    /**

-     * Makes the given visitor visit this try catch block.

-     * 

-     * @param mv a method visitor.

-     */

-    public void accept(final MethodVisitor mv) {

-        mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null

-                ? null

-                : handler.getLabel(), type);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/TypeInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/TypeInsnNode.java
deleted file mode 100644
index eeeab03..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/TypeInsnNode.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a type instruction. A type instruction is an

- * instruction that takes a type descriptor as parameter.

- * 

- * @author Eric Bruneton

- */

-public class TypeInsnNode extends AbstractInsnNode {

-

-    /**

-     * The operand of this instruction. This operand is an internal name (see

-     * {@link org.mockito.asm.Type}).

-     */

-    public String desc;

-

-    /**

-     * Constructs a new {@link TypeInsnNode}.

-     * 

-     * @param opcode the opcode of the type instruction to be constructed. This

-     *        opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.

-     * @param desc the operand of the instruction to be constructed. This

-     *        operand is an internal name (see {@link org.mockito.asm.Type}).

-     */

-    public TypeInsnNode(final int opcode, final String desc) {

-        super(opcode);

-        this.desc = desc;

-    }

-

-    /**

-     * Sets the opcode of this instruction.

-     * 

-     * @param opcode the new instruction opcode. This opcode must be NEW,

-     *        ANEWARRAY, CHECKCAST or INSTANCEOF.

-     */

-    public void setOpcode(final int opcode) {

-        this.opcode = opcode;

-    }

-

-    public int getType() {

-        return TYPE_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitTypeInsn(opcode, desc);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new TypeInsnNode(opcode, desc);

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/VarInsnNode.java b/cglib-and-asm/src/org/mockito/asm/tree/VarInsnNode.java
deleted file mode 100644
index b8d65d7..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/VarInsnNode.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree;

-

-import java.util.Map;

-

-import org.mockito.asm.MethodVisitor;

-

-/**

- * A node that represents a local variable instruction. A local variable

- * instruction is an instruction that loads or stores the value of a local

- * variable.

- * 

- * @author Eric Bruneton

- */

-public class VarInsnNode extends AbstractInsnNode {

-

-    /**

-     * The operand of this instruction. This operand is the index of a local

-     * variable.

-     */

-    public int var;

-

-    /**

-     * Constructs a new {@link VarInsnNode}.

-     * 

-     * @param opcode the opcode of the local variable instruction to be

-     *        constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,

-     *        ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.

-     * @param var the operand of the instruction to be constructed. This operand

-     *        is the index of a local variable.

-     */

-    public VarInsnNode(final int opcode, final int var) {

-        super(opcode);

-        this.var = var;

-    }

-

-    /**

-     * Sets the opcode of this instruction.

-     * 

-     * @param opcode the new instruction opcode. This opcode must be ILOAD,

-     *        LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE

-     *        or RET.

-     */

-    public void setOpcode(final int opcode) {

-        this.opcode = opcode;

-    }

-

-    public int getType() {

-        return VAR_INSN;

-    }

-

-    public void accept(final MethodVisitor mv) {

-        mv.visitVarInsn(opcode, var);

-    }

-

-    public AbstractInsnNode clone(final Map labels) {

-        return new VarInsnNode(opcode, var);

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Analyzer.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/Analyzer.java
deleted file mode 100644
index 3888146..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Analyzer.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.ArrayList;

-import java.util.HashMap;

-import java.util.List;

-import java.util.Map;

-

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.AbstractInsnNode;

-import org.mockito.asm.tree.IincInsnNode;

-import org.mockito.asm.tree.InsnList;

-import org.mockito.asm.tree.JumpInsnNode;

-import org.mockito.asm.tree.LabelNode;

-import org.mockito.asm.tree.LookupSwitchInsnNode;

-import org.mockito.asm.tree.MethodNode;

-import org.mockito.asm.tree.TableSwitchInsnNode;

-import org.mockito.asm.tree.TryCatchBlockNode;

-import org.mockito.asm.tree.VarInsnNode;

-

-/**

- * A semantic bytecode analyzer. <i>This class does not fully check that JSR and

- * RET instructions are valid.</i>

- * 

- * @author Eric Bruneton

- */

-public class Analyzer implements Opcodes {

-

-    private final Interpreter interpreter;

-

-    private int n;

-

-    private InsnList insns;

-

-    private List[] handlers;

-

-    private Frame[] frames;

-

-    private Subroutine[] subroutines;

-

-    private boolean[] queued;

-

-    private int[] queue;

-

-    private int top;

-

-    /**

-     * Constructs a new {@link Analyzer}.

-     * 

-     * @param interpreter the interpreter to be used to symbolically interpret

-     *        the bytecode instructions.

-     */

-    public Analyzer(final Interpreter interpreter) {

-        this.interpreter = interpreter;

-    }

-

-    /**

-     * Analyzes the given method.

-     * 

-     * @param owner the internal name of the class to which the method belongs.

-     * @param m the method to be analyzed.

-     * @return the symbolic state of the execution stack frame at each bytecode

-     *         instruction of the method. The size of the returned array is

-     *         equal to the number of instructions (and labels) of the method. A

-     *         given frame is <tt>null</tt> if and only if the corresponding

-     *         instruction cannot be reached (dead code).

-     * @throws AnalyzerException if a problem occurs during the analysis.

-     */

-    public Frame[] analyze(final String owner, final MethodNode m)

-            throws AnalyzerException

-    {

-        if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {

-            frames = new Frame[0];

-            return frames;

-        }

-        n = m.instructions.size();

-        insns = m.instructions;

-        handlers = new List[n];

-        frames = new Frame[n];

-        subroutines = new Subroutine[n];

-        queued = new boolean[n];

-        queue = new int[n];

-        top = 0;

-

-        // computes exception handlers for each instruction

-        for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {

-            TryCatchBlockNode tcb = (TryCatchBlockNode) m.tryCatchBlocks.get(i);

-            int begin = insns.indexOf(tcb.start);

-            int end = insns.indexOf(tcb.end);

-            for (int j = begin; j < end; ++j) {

-                List insnHandlers = handlers[j];

-                if (insnHandlers == null) {

-                    insnHandlers = new ArrayList();

-                    handlers[j] = insnHandlers;

-                }

-                insnHandlers.add(tcb);

-            }

-        }

-

-        // computes the subroutine for each instruction:

-        Subroutine main = new Subroutine(null, m.maxLocals, null);

-        List subroutineCalls = new ArrayList();

-        Map subroutineHeads = new HashMap();

-        findSubroutine(0, main, subroutineCalls);

-        while (!subroutineCalls.isEmpty()) {

-            JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);

-            Subroutine sub = (Subroutine) subroutineHeads.get(jsr.label);

-            if (sub == null) {

-                sub = new Subroutine(jsr.label, m.maxLocals, jsr);

-                subroutineHeads.put(jsr.label, sub);

-                findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);

-            } else {

-                sub.callers.add(jsr);

-            }

-        }

-        for (int i = 0; i < n; ++i) {

-            if (subroutines[i] != null && subroutines[i].start == null) {

-                subroutines[i] = null;

-            }

-        }

-

-        // initializes the data structures for the control flow analysis

-        Frame current = newFrame(m.maxLocals, m.maxStack);

-        Frame handler = newFrame(m.maxLocals, m.maxStack);

-        Type[] args = Type.getArgumentTypes(m.desc);

-        int local = 0;

-        if ((m.access & ACC_STATIC) == 0) {

-            Type ctype = Type.getObjectType(owner);

-            current.setLocal(local++, interpreter.newValue(ctype));

-        }

-        for (int i = 0; i < args.length; ++i) {

-            current.setLocal(local++, interpreter.newValue(args[i]));

-            if (args[i].getSize() == 2) {

-                current.setLocal(local++, interpreter.newValue(null));

-            }

-        }

-        while (local < m.maxLocals) {

-            current.setLocal(local++, interpreter.newValue(null));

-        }

-        merge(0, current, null);

-

-        // control flow analysis

-        while (top > 0) {

-            int insn = queue[--top];

-            Frame f = frames[insn];

-            Subroutine subroutine = subroutines[insn];

-            queued[insn] = false;

-

-            try {

-                AbstractInsnNode insnNode = m.instructions.get(insn);

-                int insnOpcode = insnNode.getOpcode();

-                int insnType = insnNode.getType();

-

-                if (insnType == AbstractInsnNode.LABEL

-                        || insnType == AbstractInsnNode.LINE

-                        || insnType == AbstractInsnNode.FRAME)

-                {

-                    merge(insn + 1, f, subroutine);

-                    newControlFlowEdge(insn, insn + 1);

-                } else {

-                    current.init(f).execute(insnNode, interpreter);

-                    subroutine = subroutine == null ? null : subroutine.copy();

-

-                    if (insnNode instanceof JumpInsnNode) {

-                        JumpInsnNode j = (JumpInsnNode) insnNode;

-                        if (insnOpcode != GOTO && insnOpcode != JSR) {

-                            merge(insn + 1, current, subroutine);

-                            newControlFlowEdge(insn, insn + 1);

-                        }

-                        int jump = insns.indexOf(j.label);

-                        if (insnOpcode == JSR) {

-                            merge(jump, current, new Subroutine(j.label,

-                                    m.maxLocals,

-                                    j));

-                        } else {

-                            merge(jump, current, subroutine);

-                        }

-                        newControlFlowEdge(insn, jump);

-                    } else if (insnNode instanceof LookupSwitchInsnNode) {

-                        LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;

-                        int jump = insns.indexOf(lsi.dflt);

-                        merge(jump, current, subroutine);

-                        newControlFlowEdge(insn, jump);

-                        for (int j = 0; j < lsi.labels.size(); ++j) {

-                            LabelNode label = (LabelNode) lsi.labels.get(j);

-                            jump = insns.indexOf(label);

-                            merge(jump, current, subroutine);

-                            newControlFlowEdge(insn, jump);

-                        }

-                    } else if (insnNode instanceof TableSwitchInsnNode) {

-                        TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;

-                        int jump = insns.indexOf(tsi.dflt);

-                        merge(jump, current, subroutine);

-                        newControlFlowEdge(insn, jump);

-                        for (int j = 0; j < tsi.labels.size(); ++j) {

-                            LabelNode label = (LabelNode) tsi.labels.get(j);

-                            jump = insns.indexOf(label);

-                            merge(jump, current, subroutine);

-                            newControlFlowEdge(insn, jump);

-                        }

-                    } else if (insnOpcode == RET) {

-                        if (subroutine == null) {

-                            throw new AnalyzerException("RET instruction outside of a sub routine");

-                        }

-                        for (int i = 0; i < subroutine.callers.size(); ++i) {

-                            Object caller = subroutine.callers.get(i);

-                            int call = insns.indexOf((AbstractInsnNode) caller);

-                            if (frames[call] != null) {

-                                merge(call + 1,

-                                        frames[call],

-                                        current,

-                                        subroutines[call],

-                                        subroutine.access);

-                                newControlFlowEdge(insn, call + 1);

-                            }

-                        }

-                    } else if (insnOpcode != ATHROW

-                            && (insnOpcode < IRETURN || insnOpcode > RETURN))

-                    {

-                        if (subroutine != null) {

-                            if (insnNode instanceof VarInsnNode) {

-                                int var = ((VarInsnNode) insnNode).var;

-                                subroutine.access[var] = true;

-                                if (insnOpcode == LLOAD || insnOpcode == DLOAD

-                                        || insnOpcode == LSTORE

-                                        || insnOpcode == DSTORE)

-                                {

-                                    subroutine.access[var + 1] = true;

-                                }

-                            } else if (insnNode instanceof IincInsnNode) {

-                                int var = ((IincInsnNode) insnNode).var;

-                                subroutine.access[var] = true;

-                            }

-                        }

-                        merge(insn + 1, current, subroutine);

-                        newControlFlowEdge(insn, insn + 1);

-                    }

-                }

-

-                List insnHandlers = handlers[insn];

-                if (insnHandlers != null) {

-                    for (int i = 0; i < insnHandlers.size(); ++i) {

-                        TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i);

-                        Type type;

-                        if (tcb.type == null) {

-                            type = Type.getObjectType("java/lang/Throwable");

-                        } else {

-                            type = Type.getObjectType(tcb.type);

-                        }

-                        int jump = insns.indexOf(tcb.handler);

-                        if (newControlFlowExceptionEdge(insn, jump)) {

-                            handler.init(f);

-                            handler.clearStack();

-                            handler.push(interpreter.newValue(type));

-                            merge(jump, handler, subroutine);

-                        }

-                    }

-                }

-            } catch (AnalyzerException e) {

-                throw new AnalyzerException("Error at instruction " + insn

-                        + ": " + e.getMessage(), e);

-            } catch (Exception e) {

-                throw new AnalyzerException("Error at instruction " + insn

-                        + ": " + e.getMessage(), e);

-            }

-        }

-

-        return frames;

-    }

-

-    private void findSubroutine(int insn, final Subroutine sub, final List calls)

-            throws AnalyzerException

-    {

-        while (true) {

-            if (insn < 0 || insn >= n) {

-                throw new AnalyzerException("Execution can fall off end of the code");

-            }

-            if (subroutines[insn] != null) {

-                return;

-            }

-            subroutines[insn] = sub.copy();

-            AbstractInsnNode node = insns.get(insn);

-

-            // calls findSubroutine recursively on normal successors

-            if (node instanceof JumpInsnNode) {

-                if (node.getOpcode() == JSR) {

-                    // do not follow a JSR, it leads to another subroutine!

-                    calls.add(node);

-                } else {

-                    JumpInsnNode jnode = (JumpInsnNode) node;

-                    findSubroutine(insns.indexOf(jnode.label), sub, calls);

-                }

-            } else if (node instanceof TableSwitchInsnNode) {

-                TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;

-                findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);

-                for (int i = tsnode.labels.size() - 1; i >= 0; --i) {

-                    LabelNode l = (LabelNode) tsnode.labels.get(i);

-                    findSubroutine(insns.indexOf(l), sub, calls);

-                }

-            } else if (node instanceof LookupSwitchInsnNode) {

-                LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;

-                findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);

-                for (int i = lsnode.labels.size() - 1; i >= 0; --i) {

-                    LabelNode l = (LabelNode) lsnode.labels.get(i);

-                    findSubroutine(insns.indexOf(l), sub, calls);

-                }

-            }

-

-            // calls findSubroutine recursively on exception handler successors

-            List insnHandlers = handlers[insn];

-            if (insnHandlers != null) {

-                for (int i = 0; i < insnHandlers.size(); ++i) {

-                    TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i);

-                    findSubroutine(insns.indexOf(tcb.handler), sub, calls);

-                }

-            }

-

-            // if insn does not falls through to the next instruction, return.

-            switch (node.getOpcode()) {

-                case GOTO:

-                case RET:

-                case TABLESWITCH:

-                case LOOKUPSWITCH:

-                case IRETURN:

-                case LRETURN:

-                case FRETURN:

-                case DRETURN:

-                case ARETURN:

-                case RETURN:

-                case ATHROW:

-                    return;

-            }

-            insn++;

-        }

-    }

-

-    /**

-     * Returns the symbolic stack frame for each instruction of the last

-     * recently analyzed method.

-     * 

-     * @return the symbolic state of the execution stack frame at each bytecode

-     *         instruction of the method. The size of the returned array is

-     *         equal to the number of instructions (and labels) of the method. A

-     *         given frame is <tt>null</tt> if the corresponding instruction

-     *         cannot be reached, or if an error occured during the analysis of

-     *         the method.

-     */

-    public Frame[] getFrames() {

-        return frames;

-    }

-

-    /**

-     * Returns the exception handlers for the given instruction.

-     * 

-     * @param insn the index of an instruction of the last recently analyzed

-     *        method.

-     * @return a list of {@link TryCatchBlockNode} objects.

-     */

-    public List getHandlers(final int insn) {

-        return handlers[insn];

-    }

-

-    /**

-     * Constructs a new frame with the given size.

-     * 

-     * @param nLocals the maximum number of local variables of the frame.

-     * @param nStack the maximum stack size of the frame.

-     * @return the created frame.

-     */

-    protected Frame newFrame(final int nLocals, final int nStack) {

-        return new Frame(nLocals, nStack);

-    }

-

-    /**

-     * Constructs a new frame that is identical to the given frame.

-     * 

-     * @param src a frame.

-     * @return the created frame.

-     */

-    protected Frame newFrame(final Frame src) {

-        return new Frame(src);

-    }

-

-    /**

-     * Creates a control flow graph edge. The default implementation of this

-     * method does nothing. It can be overriden in order to construct the

-     * control flow graph of a method (this method is called by the

-     * {@link #analyze analyze} method during its visit of the method's code).

-     * 

-     * @param insn an instruction index.

-     * @param successor index of a successor instruction.

-     */

-    protected void newControlFlowEdge(final int insn, final int successor) {

-    }

-

-    /**

-     * Creates a control flow graph edge corresponding to an exception handler.

-     * The default implementation of this method does nothing. It can be

-     * overriden in order to construct the control flow graph of a method (this

-     * method is called by the {@link #analyze analyze} method during its visit

-     * of the method's code).

-     * 

-     * @param insn an instruction index.

-     * @param successor index of a successor instruction.

-     * @return true if this edge must be considered in the data flow analysis

-     *         performed by this analyzer, or false otherwise. The default

-     *         implementation of this method always returns true.

-     */

-    protected boolean newControlFlowExceptionEdge(

-        final int insn,

-        final int successor)

-    {

-        return true;

-    }

-

-    // -------------------------------------------------------------------------

-

-    private void merge(

-        final int insn,

-        final Frame frame,

-        final Subroutine subroutine) throws AnalyzerException

-    {

-        Frame oldFrame = frames[insn];

-        Subroutine oldSubroutine = subroutines[insn];

-        boolean changes;

-

-        if (oldFrame == null) {

-            frames[insn] = newFrame(frame);

-            changes = true;

-        } else {

-            changes = oldFrame.merge(frame, interpreter);

-        }

-

-        if (oldSubroutine == null) {

-            if (subroutine != null) {

-                subroutines[insn] = subroutine.copy();

-                changes = true;

-            }

-        } else {

-            if (subroutine != null) {

-                changes |= oldSubroutine.merge(subroutine);

-            }

-        }

-        if (changes && !queued[insn]) {

-            queued[insn] = true;

-            queue[top++] = insn;

-        }

-    }

-

-    private void merge(

-        final int insn,

-        final Frame beforeJSR,

-        final Frame afterRET,

-        final Subroutine subroutineBeforeJSR,

-        final boolean[] access) throws AnalyzerException

-    {

-        Frame oldFrame = frames[insn];

-        Subroutine oldSubroutine = subroutines[insn];

-        boolean changes;

-

-        afterRET.merge(beforeJSR, access);

-

-        if (oldFrame == null) {

-            frames[insn] = newFrame(afterRET);

-            changes = true;

-        } else {

-            changes = oldFrame.merge(afterRET, access);

-        }

-

-        if (oldSubroutine != null && subroutineBeforeJSR != null) {

-            changes |= oldSubroutine.merge(subroutineBeforeJSR);

-        }

-        if (changes && !queued[insn]) {

-            queued[insn] = true;

-            queue[top++] = insn;

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/AnalyzerException.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/AnalyzerException.java
deleted file mode 100644
index 6cf96e8..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/AnalyzerException.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-/**

- * Thrown if a problem occurs during the analysis of a method.

- * 

- * @author Bing Ran

- * @author Eric Bruneton

- */

-public class AnalyzerException extends Exception {

-

-    public AnalyzerException(final String msg) {

-        super(msg);

-    }

-

-    public AnalyzerException(final String msg, final Throwable exception) {

-        super(msg, exception);

-    }

-

-    public AnalyzerException(

-        final String msg,

-        final Object expected,

-        final Value encountered)

-    {

-        super((msg == null ? "Expected " : msg + ": expected ") + expected

-                + ", but found " + encountered);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicInterpreter.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicInterpreter.java
deleted file mode 100644
index 4b4de8c..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicInterpreter.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.List;

-

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.AbstractInsnNode;

-import org.mockito.asm.tree.FieldInsnNode;

-import org.mockito.asm.tree.IntInsnNode;

-import org.mockito.asm.tree.LdcInsnNode;

-import org.mockito.asm.tree.MethodInsnNode;

-import org.mockito.asm.tree.MultiANewArrayInsnNode;

-import org.mockito.asm.tree.TypeInsnNode;

-

-/**

- * An {@link Interpreter} for {@link BasicValue} values.

- * 

- * @author Eric Bruneton

- * @author Bing Ran

- */

-public class BasicInterpreter implements Opcodes, Interpreter {

-

-    public Value newValue(final Type type) {

-        if (type == null) {

-            return BasicValue.UNINITIALIZED_VALUE;

-        }

-        switch (type.getSort()) {

-            case Type.VOID:

-                return null;

-            case Type.BOOLEAN:

-            case Type.CHAR:

-            case Type.BYTE:

-            case Type.SHORT:

-            case Type.INT:

-                return BasicValue.INT_VALUE;

-            case Type.FLOAT:

-                return BasicValue.FLOAT_VALUE;

-            case Type.LONG:

-                return BasicValue.LONG_VALUE;

-            case Type.DOUBLE:

-                return BasicValue.DOUBLE_VALUE;

-            case Type.ARRAY:

-            case Type.OBJECT:

-                return BasicValue.REFERENCE_VALUE;

-            default:

-                throw new Error("Internal error");

-        }

-    }

-

-    public Value newOperation(final AbstractInsnNode insn) {

-        switch (insn.getOpcode()) {

-            case ACONST_NULL:

-                return newValue(Type.getObjectType("null"));

-            case ICONST_M1:

-            case ICONST_0:

-            case ICONST_1:

-            case ICONST_2:

-            case ICONST_3:

-            case ICONST_4:

-            case ICONST_5:

-                return BasicValue.INT_VALUE;

-            case LCONST_0:

-            case LCONST_1:

-                return BasicValue.LONG_VALUE;

-            case FCONST_0:

-            case FCONST_1:

-            case FCONST_2:

-                return BasicValue.FLOAT_VALUE;

-            case DCONST_0:

-            case DCONST_1:

-                return BasicValue.DOUBLE_VALUE;

-            case BIPUSH:

-            case SIPUSH:

-                return BasicValue.INT_VALUE;

-            case LDC:

-                Object cst = ((LdcInsnNode) insn).cst;

-                if (cst instanceof Integer) {

-                    return BasicValue.INT_VALUE;

-                } else if (cst instanceof Float) {

-                    return BasicValue.FLOAT_VALUE;

-                } else if (cst instanceof Long) {

-                    return BasicValue.LONG_VALUE;

-                } else if (cst instanceof Double) {

-                    return BasicValue.DOUBLE_VALUE;

-                } else if (cst instanceof Type) {

-                    return newValue(Type.getObjectType("java/lang/Class"));

-                } else {

-                    return newValue(Type.getType(cst.getClass()));

-                }

-            case JSR:

-                return BasicValue.RETURNADDRESS_VALUE;

-            case GETSTATIC:

-                return newValue(Type.getType(((FieldInsnNode) insn).desc));

-            case NEW:

-                return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));

-            default:

-                throw new Error("Internal error.");

-        }

-    }

-

-    public Value copyOperation(final AbstractInsnNode insn, final Value value)

-            throws AnalyzerException

-    {

-        return value;

-    }

-

-    public Value unaryOperation(final AbstractInsnNode insn, final Value value)

-            throws AnalyzerException

-    {

-        switch (insn.getOpcode()) {

-            case INEG:

-            case IINC:

-            case L2I:

-            case F2I:

-            case D2I:

-            case I2B:

-            case I2C:

-            case I2S:

-                return BasicValue.INT_VALUE;

-            case FNEG:

-            case I2F:

-            case L2F:

-            case D2F:

-                return BasicValue.FLOAT_VALUE;

-            case LNEG:

-            case I2L:

-            case F2L:

-            case D2L:

-                return BasicValue.LONG_VALUE;

-            case DNEG:

-            case I2D:

-            case L2D:

-            case F2D:

-                return BasicValue.DOUBLE_VALUE;

-            case IFEQ:

-            case IFNE:

-            case IFLT:

-            case IFGE:

-            case IFGT:

-            case IFLE:

-            case TABLESWITCH:

-            case LOOKUPSWITCH:

-            case IRETURN:

-            case LRETURN:

-            case FRETURN:

-            case DRETURN:

-            case ARETURN:

-            case PUTSTATIC:

-                return null;

-            case GETFIELD:

-                return newValue(Type.getType(((FieldInsnNode) insn).desc));

-            case NEWARRAY:

-                switch (((IntInsnNode) insn).operand) {

-                    case T_BOOLEAN:

-                        return newValue(Type.getType("[Z"));

-                    case T_CHAR:

-                        return newValue(Type.getType("[C"));

-                    case T_BYTE:

-                        return newValue(Type.getType("[B"));

-                    case T_SHORT:

-                        return newValue(Type.getType("[S"));

-                    case T_INT:

-                        return newValue(Type.getType("[I"));

-                    case T_FLOAT:

-                        return newValue(Type.getType("[F"));

-                    case T_DOUBLE:

-                        return newValue(Type.getType("[D"));

-                    case T_LONG:

-                        return newValue(Type.getType("[J"));

-                    default:

-                        throw new AnalyzerException("Invalid array type");

-                }

-            case ANEWARRAY:

-                String desc = ((TypeInsnNode) insn).desc;

-                return newValue(Type.getType("[" + Type.getObjectType(desc)));

-            case ARRAYLENGTH:

-                return BasicValue.INT_VALUE;

-            case ATHROW:

-                return null;

-            case CHECKCAST:

-                desc = ((TypeInsnNode) insn).desc;

-                return newValue(Type.getObjectType(desc));

-            case INSTANCEOF:

-                return BasicValue.INT_VALUE;

-            case MONITORENTER:

-            case MONITOREXIT:

-            case IFNULL:

-            case IFNONNULL:

-                return null;

-            default:

-                throw new Error("Internal error.");

-        }

-    }

-

-    public Value binaryOperation(

-        final AbstractInsnNode insn,

-        final Value value1,

-        final Value value2) throws AnalyzerException

-    {

-        switch (insn.getOpcode()) {

-            case IALOAD:

-            case BALOAD:

-            case CALOAD:

-            case SALOAD:

-            case IADD:

-            case ISUB:

-            case IMUL:

-            case IDIV:

-            case IREM:

-            case ISHL:

-            case ISHR:

-            case IUSHR:

-            case IAND:

-            case IOR:

-            case IXOR:

-                return BasicValue.INT_VALUE;

-            case FALOAD:

-            case FADD:

-            case FSUB:

-            case FMUL:

-            case FDIV:

-            case FREM:

-                return BasicValue.FLOAT_VALUE;

-            case LALOAD:

-            case LADD:

-            case LSUB:

-            case LMUL:

-            case LDIV:

-            case LREM:

-            case LSHL:

-            case LSHR:

-            case LUSHR:

-            case LAND:

-            case LOR:

-            case LXOR:

-                return BasicValue.LONG_VALUE;

-            case DALOAD:

-            case DADD:

-            case DSUB:

-            case DMUL:

-            case DDIV:

-            case DREM:

-                return BasicValue.DOUBLE_VALUE;

-            case AALOAD:

-                return BasicValue.REFERENCE_VALUE;

-            case LCMP:

-            case FCMPL:

-            case FCMPG:

-            case DCMPL:

-            case DCMPG:

-                return BasicValue.INT_VALUE;

-            case IF_ICMPEQ:

-            case IF_ICMPNE:

-            case IF_ICMPLT:

-            case IF_ICMPGE:

-            case IF_ICMPGT:

-            case IF_ICMPLE:

-            case IF_ACMPEQ:

-            case IF_ACMPNE:

-            case PUTFIELD:

-                return null;

-            default:

-                throw new Error("Internal error.");

-        }

-    }

-

-    public Value ternaryOperation(

-        final AbstractInsnNode insn,

-        final Value value1,

-        final Value value2,

-        final Value value3) throws AnalyzerException

-    {

-        return null;

-    }

-

-    public Value naryOperation(final AbstractInsnNode insn, final List values)

-            throws AnalyzerException

-    {

-        if (insn.getOpcode() == MULTIANEWARRAY) {

-            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));

-        } else {

-            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));

-        }

-    }

-

-    public Value merge(final Value v, final Value w) {

-        if (!v.equals(w)) {

-            return BasicValue.UNINITIALIZED_VALUE;

-        }

-        return v;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicValue.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicValue.java
deleted file mode 100644
index d772dbe..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicValue.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import org.mockito.asm.Type;

-

-/**

- * A {@link Value} that is represented by its type in a seven types type system.

- * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,

- * REFERENCE and RETURNADDRESS types.

- * 

- * @author Eric Bruneton

- */

-public class BasicValue implements Value {

-

-    public static final Value UNINITIALIZED_VALUE = new BasicValue(null);

-

-    public static final Value INT_VALUE = new BasicValue(Type.INT_TYPE);

-

-    public static final Value FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);

-

-    public static final Value LONG_VALUE = new BasicValue(Type.LONG_TYPE);

-

-    public static final Value DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE);

-

-    public static final Value REFERENCE_VALUE = new BasicValue(Type.getObjectType("java/lang/Object"));

-

-    public static final Value RETURNADDRESS_VALUE = new BasicValue(null);

-

-    private final Type type;

-

-    public BasicValue(final Type type) {

-        this.type = type;

-    }

-

-    public Type getType() {

-        return type;

-    }

-

-    public int getSize() {

-        return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;

-    }

-

-    public boolean isReference() {

-        return type != null

-                && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);

-    }

-

-    public boolean equals(final Object value) {

-        if (value == this) {

-            return true;

-        } else if (value instanceof BasicValue) {

-            if (type == null) {

-                return ((BasicValue) value).type == null;

-            } else {

-                return type.equals(((BasicValue) value).type);

-            }

-        } else {

-            return false;

-        }

-    }

-

-    public int hashCode() {

-        return type == null ? 0 : type.hashCode();

-    }

-

-    public String toString() {

-        if (this == UNINITIALIZED_VALUE) {

-            return ".";

-        } else if (this == RETURNADDRESS_VALUE) {

-            return "A";

-        } else if (this == REFERENCE_VALUE) {

-            return "R";

-        } else {

-            return type.getDescriptor();

-        }

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicVerifier.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicVerifier.java
deleted file mode 100644
index beba62c..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/BasicVerifier.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.List;

-

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.AbstractInsnNode;

-import org.mockito.asm.tree.FieldInsnNode;

-import org.mockito.asm.tree.MethodInsnNode;

-

-/**

- * An extended {@link BasicInterpreter} that checks that bytecode instructions

- * are correctly used.

- * 

- * @author Eric Bruneton

- * @author Bing Ran

- */

-public class BasicVerifier extends BasicInterpreter {

-

-    public Value copyOperation(final AbstractInsnNode insn, final Value value)

-            throws AnalyzerException

-    {

-        Value expected;

-        switch (insn.getOpcode()) {

-            case ILOAD:

-            case ISTORE:

-                expected = BasicValue.INT_VALUE;

-                break;

-            case FLOAD:

-            case FSTORE:

-                expected = BasicValue.FLOAT_VALUE;

-                break;

-            case LLOAD:

-            case LSTORE:

-                expected = BasicValue.LONG_VALUE;

-                break;

-            case DLOAD:

-            case DSTORE:

-                expected = BasicValue.DOUBLE_VALUE;

-                break;

-            case ALOAD:

-                if (!((BasicValue) value).isReference()) {

-                    throw new AnalyzerException(null,

-                            "an object reference",

-                            value);

-                }

-                return value;

-            case ASTORE:

-                if (!((BasicValue) value).isReference()

-                        && value != BasicValue.RETURNADDRESS_VALUE)

-                {

-                    throw new AnalyzerException(null,

-                            "an object reference or a return address",

-                            value);

-                }

-                return value;

-            default:

-                return value;

-        }

-        // type is necessarily a primitive type here,

-        // so value must be == to expected value

-        if (value != expected) {

-            throw new AnalyzerException(null, expected, value);

-        }

-        return value;

-    }

-

-    public Value unaryOperation(final AbstractInsnNode insn, final Value value)

-            throws AnalyzerException

-    {

-        Value expected;

-        switch (insn.getOpcode()) {

-            case INEG:

-            case IINC:

-            case I2F:

-            case I2L:

-            case I2D:

-            case I2B:

-            case I2C:

-            case I2S:

-            case IFEQ:

-            case IFNE:

-            case IFLT:

-            case IFGE:

-            case IFGT:

-            case IFLE:

-            case TABLESWITCH:

-            case LOOKUPSWITCH:

-            case IRETURN:

-            case NEWARRAY:

-            case ANEWARRAY:

-                expected = BasicValue.INT_VALUE;

-                break;

-            case FNEG:

-            case F2I:

-            case F2L:

-            case F2D:

-            case FRETURN:

-                expected = BasicValue.FLOAT_VALUE;

-                break;

-            case LNEG:

-            case L2I:

-            case L2F:

-            case L2D:

-            case LRETURN:

-                expected = BasicValue.LONG_VALUE;

-                break;

-            case DNEG:

-            case D2I:

-            case D2F:

-            case D2L:

-            case DRETURN:

-                expected = BasicValue.DOUBLE_VALUE;

-                break;

-            case GETFIELD:

-                expected = newValue(Type.getObjectType(((FieldInsnNode) insn).owner));

-                break;

-            case CHECKCAST:

-                if (!((BasicValue) value).isReference()) {

-                    throw new AnalyzerException(null,

-                            "an object reference",

-                            value);

-                }

-                return super.unaryOperation(insn, value);

-            case ARRAYLENGTH:

-                if (!isArrayValue(value)) {

-                    throw new AnalyzerException(null,

-                            "an array reference",

-                            value);

-                }

-                return super.unaryOperation(insn, value);

-            case ARETURN:

-            case ATHROW:

-            case INSTANCEOF:

-            case MONITORENTER:

-            case MONITOREXIT:

-            case IFNULL:

-            case IFNONNULL:

-                if (!((BasicValue) value).isReference()) {

-                    throw new AnalyzerException(null,

-                            "an object reference",

-                            value);

-                }

-                return super.unaryOperation(insn, value);

-            case PUTSTATIC:

-                expected = newValue(Type.getType(((FieldInsnNode) insn).desc));

-                break;

-            default:

-                throw new Error("Internal error.");

-        }

-        if (!isSubTypeOf(value, expected)) {

-            throw new AnalyzerException(null, expected, value);

-        }

-        return super.unaryOperation(insn, value);

-    }

-

-    public Value binaryOperation(

-        final AbstractInsnNode insn,

-        final Value value1,

-        final Value value2) throws AnalyzerException

-    {

-        Value expected1;

-        Value expected2;

-        switch (insn.getOpcode()) {

-            case IALOAD:

-                expected1 = newValue(Type.getType("[I"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case BALOAD:

-                if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {

-                    expected1 = newValue(Type.getType("[Z"));

-                } else {

-                    expected1 = newValue(Type.getType("[B"));

-                }

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case CALOAD:

-                expected1 = newValue(Type.getType("[C"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case SALOAD:

-                expected1 = newValue(Type.getType("[S"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case LALOAD:

-                expected1 = newValue(Type.getType("[J"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case FALOAD:

-                expected1 = newValue(Type.getType("[F"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case DALOAD:

-                expected1 = newValue(Type.getType("[D"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case AALOAD:

-                expected1 = newValue(Type.getType("[Ljava/lang/Object;"));

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case IADD:

-            case ISUB:

-            case IMUL:

-            case IDIV:

-            case IREM:

-            case ISHL:

-            case ISHR:

-            case IUSHR:

-            case IAND:

-            case IOR:

-            case IXOR:

-            case IF_ICMPEQ:

-            case IF_ICMPNE:

-            case IF_ICMPLT:

-            case IF_ICMPGE:

-            case IF_ICMPGT:

-            case IF_ICMPLE:

-                expected1 = BasicValue.INT_VALUE;

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case FADD:

-            case FSUB:

-            case FMUL:

-            case FDIV:

-            case FREM:

-            case FCMPL:

-            case FCMPG:

-                expected1 = BasicValue.FLOAT_VALUE;

-                expected2 = BasicValue.FLOAT_VALUE;

-                break;

-            case LADD:

-            case LSUB:

-            case LMUL:

-            case LDIV:

-            case LREM:

-            case LAND:

-            case LOR:

-            case LXOR:

-            case LCMP:

-                expected1 = BasicValue.LONG_VALUE;

-                expected2 = BasicValue.LONG_VALUE;

-                break;

-            case LSHL:

-            case LSHR:

-            case LUSHR:

-                expected1 = BasicValue.LONG_VALUE;

-                expected2 = BasicValue.INT_VALUE;

-                break;

-            case DADD:

-            case DSUB:

-            case DMUL:

-            case DDIV:

-            case DREM:

-            case DCMPL:

-            case DCMPG:

-                expected1 = BasicValue.DOUBLE_VALUE;

-                expected2 = BasicValue.DOUBLE_VALUE;

-                break;

-            case IF_ACMPEQ:

-            case IF_ACMPNE:

-                expected1 = BasicValue.REFERENCE_VALUE;

-                expected2 = BasicValue.REFERENCE_VALUE;

-                break;

-            case PUTFIELD:

-                FieldInsnNode fin = (FieldInsnNode) insn;

-                expected1 = newValue(Type.getObjectType(fin.owner));

-                expected2 = newValue(Type.getType(fin.desc));

-                break;

-            default:

-                throw new Error("Internal error.");

-        }

-        if (!isSubTypeOf(value1, expected1)) {

-            throw new AnalyzerException("First argument", expected1, value1);

-        } else if (!isSubTypeOf(value2, expected2)) {

-            throw new AnalyzerException("Second argument", expected2, value2);

-        }

-        if (insn.getOpcode() == AALOAD) {

-            return getElementValue(value1);

-        } else {

-            return super.binaryOperation(insn, value1, value2);

-        }

-    }

-

-    public Value ternaryOperation(

-        final AbstractInsnNode insn,

-        final Value value1,

-        final Value value2,

-        final Value value3) throws AnalyzerException

-    {

-        Value expected1;

-        Value expected3;

-        switch (insn.getOpcode()) {

-            case IASTORE:

-                expected1 = newValue(Type.getType("[I"));

-                expected3 = BasicValue.INT_VALUE;

-                break;

-            case BASTORE:

-                if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {

-                    expected1 = newValue(Type.getType("[Z"));

-                } else {

-                    expected1 = newValue(Type.getType("[B"));

-                }

-                expected3 = BasicValue.INT_VALUE;

-                break;

-            case CASTORE:

-                expected1 = newValue(Type.getType("[C"));

-                expected3 = BasicValue.INT_VALUE;

-                break;

-            case SASTORE:

-                expected1 = newValue(Type.getType("[S"));

-                expected3 = BasicValue.INT_VALUE;

-                break;

-            case LASTORE:

-                expected1 = newValue(Type.getType("[J"));

-                expected3 = BasicValue.LONG_VALUE;

-                break;

-            case FASTORE:

-                expected1 = newValue(Type.getType("[F"));

-                expected3 = BasicValue.FLOAT_VALUE;

-                break;

-            case DASTORE:

-                expected1 = newValue(Type.getType("[D"));

-                expected3 = BasicValue.DOUBLE_VALUE;

-                break;

-            case AASTORE:

-                expected1 = value1;

-                expected3 = BasicValue.REFERENCE_VALUE;

-                break;

-            default:

-                throw new Error("Internal error.");

-        }

-        if (!isSubTypeOf(value1, expected1)) {

-            throw new AnalyzerException("First argument", "a " + expected1

-                    + " array reference", value1);

-        } else if (value2 != BasicValue.INT_VALUE) {

-            throw new AnalyzerException("Second argument",

-                    BasicValue.INT_VALUE,

-                    value2);

-        } else if (!isSubTypeOf(value3, expected3)) {

-            throw new AnalyzerException("Third argument", expected3, value3);

-        }

-        return null;

-    }

-

-    public Value naryOperation(final AbstractInsnNode insn, final List values)

-            throws AnalyzerException

-    {

-        int opcode = insn.getOpcode();

-        if (opcode == MULTIANEWARRAY) {

-            for (int i = 0; i < values.size(); ++i) {

-                if (values.get(i) != BasicValue.INT_VALUE) {

-                    throw new AnalyzerException(null,

-                            BasicValue.INT_VALUE,

-                            (Value) values.get(i));

-                }

-            }

-        } else {

-            int i = 0;

-            int j = 0;

-            if (opcode != INVOKESTATIC) {

-                Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);

-                if (!isSubTypeOf((Value) values.get(i++), newValue(owner))) {

-                    throw new AnalyzerException("Method owner",

-                            newValue(owner),

-                            (Value) values.get(0));

-                }

-            }

-            Type[] args = Type.getArgumentTypes(((MethodInsnNode) insn).desc);

-            while (i < values.size()) {

-                Value expected = newValue(args[j++]);

-                Value encountered = (Value) values.get(i++);

-                if (!isSubTypeOf(encountered, expected)) {

-                    throw new AnalyzerException("Argument " + j,

-                            expected,

-                            encountered);

-                }

-            }

-        }

-        return super.naryOperation(insn, values);

-    }

-

-    protected boolean isArrayValue(final Value value) {

-        return ((BasicValue) value).isReference();

-    }

-

-    protected Value getElementValue(final Value objectArrayValue)

-            throws AnalyzerException

-    {

-        return BasicValue.REFERENCE_VALUE;

-    }

-

-    protected boolean isSubTypeOf(final Value value, final Value expected) {

-        return value == expected;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Frame.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/Frame.java
deleted file mode 100644
index 369fa61..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Frame.java
+++ /dev/null
@@ -1,667 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.ArrayList;

-import java.util.List;

-

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.AbstractInsnNode;

-import org.mockito.asm.tree.IincInsnNode;

-import org.mockito.asm.tree.MethodInsnNode;

-import org.mockito.asm.tree.MultiANewArrayInsnNode;

-import org.mockito.asm.tree.VarInsnNode;

-

-/**

- * A symbolic execution stack frame. A stack frame contains a set of local

- * variable slots, and an operand stack. Warning: long and double values are

- * represented by <i>two</i> slots in local variables, and by <i>one</i> slot

- * in the operand stack.

- * 

- * @author Eric Bruneton

- */

-public class Frame {

-

-    /**

-     * The local variables and operand stack of this frame.

-     */

-    private Value[] values;

-

-    /**

-     * The number of local variables of this frame.

-     */

-    private int locals;

-

-    /**

-     * The number of elements in the operand stack.

-     */

-    private int top;

-

-    /**

-     * Constructs a new frame with the given size.

-     * 

-     * @param nLocals the maximum number of local variables of the frame.

-     * @param nStack the maximum stack size of the frame.

-     */

-    public Frame(final int nLocals, final int nStack) {

-        this.values = new Value[nLocals + nStack];

-        this.locals = nLocals;

-    }

-

-    /**

-     * Constructs a new frame that is identical to the given frame.

-     * 

-     * @param src a frame.

-     */

-    public Frame(final Frame src) {

-        this(src.locals, src.values.length - src.locals);

-        init(src);

-    }

-

-    /**

-     * Copies the state of the given frame into this frame.

-     * 

-     * @param src a frame.

-     * @return this frame.

-     */

-    public Frame init(final Frame src) {

-        System.arraycopy(src.values, 0, values, 0, values.length);

-        top = src.top;

-        return this;

-    }

-

-    /**

-     * Returns the maximum number of local variables of this frame.

-     * 

-     * @return the maximum number of local variables of this frame.

-     */

-    public int getLocals() {

-        return locals;

-    }

-

-    /**

-     * Returns the value of the given local variable.

-     * 

-     * @param i a local variable index.

-     * @return the value of the given local variable.

-     * @throws IndexOutOfBoundsException if the variable does not exist.

-     */

-    public Value getLocal(final int i) throws IndexOutOfBoundsException {

-        if (i >= locals) {

-            throw new IndexOutOfBoundsException("Trying to access an inexistant local variable");

-        }

-        return values[i];

-    }

-

-    /**

-     * Sets the value of the given local variable.

-     * 

-     * @param i a local variable index.

-     * @param value the new value of this local variable.

-     * @throws IndexOutOfBoundsException if the variable does not exist.

-     */

-    public void setLocal(final int i, final Value value)

-            throws IndexOutOfBoundsException

-    {

-        if (i >= locals) {

-            throw new IndexOutOfBoundsException("Trying to access an inexistant local variable");

-        }

-        values[i] = value;

-    }

-

-    /**

-     * Returns the number of values in the operand stack of this frame. Long and

-     * double values are treated as single values.

-     * 

-     * @return the number of values in the operand stack of this frame.

-     */

-    public int getStackSize() {

-        return top;

-    }

-

-    /**

-     * Returns the value of the given operand stack slot.

-     * 

-     * @param i the index of an operand stack slot.

-     * @return the value of the given operand stack slot.

-     * @throws IndexOutOfBoundsException if the operand stack slot does not

-     *         exist.

-     */

-    public Value getStack(final int i) throws IndexOutOfBoundsException {

-        return values[i + locals];

-    }

-

-    /**

-     * Clears the operand stack of this frame.

-     */

-    public void clearStack() {

-        top = 0;

-    }

-

-    /**

-     * Pops a value from the operand stack of this frame.

-     * 

-     * @return the value that has been popped from the stack.

-     * @throws IndexOutOfBoundsException if the operand stack is empty.

-     */

-    public Value pop() throws IndexOutOfBoundsException {

-        if (top == 0) {

-            throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack.");

-        }

-        return values[--top + locals];

-    }

-

-    /**

-     * Pushes a value into the operand stack of this frame.

-     * 

-     * @param value the value that must be pushed into the stack.

-     * @throws IndexOutOfBoundsException if the operand stack is full.

-     */

-    public void push(final Value value) throws IndexOutOfBoundsException {

-        if (top + locals >= values.length) {

-            throw new IndexOutOfBoundsException("Insufficient maximum stack size.");

-        }

-        values[top++ + locals] = value;

-    }

-

-    public void execute(

-        final AbstractInsnNode insn,

-        final Interpreter interpreter) throws AnalyzerException

-    {

-        Value value1, value2, value3, value4;

-        List values;

-        int var;

-

-        switch (insn.getOpcode()) {

-            case Opcodes.NOP:

-                break;

-            case Opcodes.ACONST_NULL:

-            case Opcodes.ICONST_M1:

-            case Opcodes.ICONST_0:

-            case Opcodes.ICONST_1:

-            case Opcodes.ICONST_2:

-            case Opcodes.ICONST_3:

-            case Opcodes.ICONST_4:

-            case Opcodes.ICONST_5:

-            case Opcodes.LCONST_0:

-            case Opcodes.LCONST_1:

-            case Opcodes.FCONST_0:

-            case Opcodes.FCONST_1:

-            case Opcodes.FCONST_2:

-            case Opcodes.DCONST_0:

-            case Opcodes.DCONST_1:

-            case Opcodes.BIPUSH:

-            case Opcodes.SIPUSH:

-            case Opcodes.LDC:

-                push(interpreter.newOperation(insn));

-                break;

-            case Opcodes.ILOAD:

-            case Opcodes.LLOAD:

-            case Opcodes.FLOAD:

-            case Opcodes.DLOAD:

-            case Opcodes.ALOAD:

-                push(interpreter.copyOperation(insn,

-                        getLocal(((VarInsnNode) insn).var)));

-                break;

-            case Opcodes.IALOAD:

-            case Opcodes.LALOAD:

-            case Opcodes.FALOAD:

-            case Opcodes.DALOAD:

-            case Opcodes.AALOAD:

-            case Opcodes.BALOAD:

-            case Opcodes.CALOAD:

-            case Opcodes.SALOAD:

-                value2 = pop();

-                value1 = pop();

-                push(interpreter.binaryOperation(insn, value1, value2));

-                break;

-            case Opcodes.ISTORE:

-            case Opcodes.LSTORE:

-            case Opcodes.FSTORE:

-            case Opcodes.DSTORE:

-            case Opcodes.ASTORE:

-                value1 = interpreter.copyOperation(insn, pop());

-                var = ((VarInsnNode) insn).var;

-                setLocal(var, value1);

-                if (value1.getSize() == 2) {

-                    setLocal(var + 1, interpreter.newValue(null));

-                }

-                if (var > 0) {

-                    Value local = getLocal(var - 1);

-                    if (local != null && local.getSize() == 2) {

-                        setLocal(var - 1, interpreter.newValue(null));

-                    }

-                }

-                break;

-            case Opcodes.IASTORE:

-            case Opcodes.LASTORE:

-            case Opcodes.FASTORE:

-            case Opcodes.DASTORE:

-            case Opcodes.AASTORE:

-            case Opcodes.BASTORE:

-            case Opcodes.CASTORE:

-            case Opcodes.SASTORE:

-                value3 = pop();

-                value2 = pop();

-                value1 = pop();

-                interpreter.ternaryOperation(insn, value1, value2, value3);

-                break;

-            case Opcodes.POP:

-                if (pop().getSize() == 2) {

-                    throw new AnalyzerException("Illegal use of POP");

-                }

-                break;

-            case Opcodes.POP2:

-                if (pop().getSize() == 1) {

-                    if (pop().getSize() != 1) {

-                        throw new AnalyzerException("Illegal use of POP2");

-                    }

-                }

-                break;

-            case Opcodes.DUP:

-                value1 = pop();

-                if (value1.getSize() != 1) {

-                    throw new AnalyzerException("Illegal use of DUP");

-                }

-                push(interpreter.copyOperation(insn, value1));

-                push(interpreter.copyOperation(insn, value1));

-                break;

-            case Opcodes.DUP_X1:

-                value1 = pop();

-                value2 = pop();

-                if (value1.getSize() != 1 || value2.getSize() != 1) {

-                    throw new AnalyzerException("Illegal use of DUP_X1");

-                }

-                push(interpreter.copyOperation(insn, value1));

-                push(interpreter.copyOperation(insn, value2));

-                push(interpreter.copyOperation(insn, value1));

-                break;

-            case Opcodes.DUP_X2:

-                value1 = pop();

-                if (value1.getSize() == 1) {

-                    value2 = pop();

-                    if (value2.getSize() == 1) {

-                        value3 = pop();

-                        if (value3.getSize() == 1) {

-                            push(interpreter.copyOperation(insn, value1));

-                            push(interpreter.copyOperation(insn, value3));

-                            push(interpreter.copyOperation(insn, value2));

-                            push(interpreter.copyOperation(insn, value1));

-                            break;

-                        }

-                    } else {

-                        push(interpreter.copyOperation(insn, value1));

-                        push(interpreter.copyOperation(insn, value2));

-                        push(interpreter.copyOperation(insn, value1));

-                        break;

-                    }

-                }

-                throw new AnalyzerException("Illegal use of DUP_X2");

-            case Opcodes.DUP2:

-                value1 = pop();

-                if (value1.getSize() == 1) {

-                    value2 = pop();

-                    if (value2.getSize() == 1) {

-                        push(interpreter.copyOperation(insn, value2));

-                        push(interpreter.copyOperation(insn, value1));

-                        push(interpreter.copyOperation(insn, value2));

-                        push(interpreter.copyOperation(insn, value1));

-                        break;

-                    }

-                } else {

-                    push(interpreter.copyOperation(insn, value1));

-                    push(interpreter.copyOperation(insn, value1));

-                    break;

-                }

-                throw new AnalyzerException("Illegal use of DUP2");

-            case Opcodes.DUP2_X1:

-                value1 = pop();

-                if (value1.getSize() == 1) {

-                    value2 = pop();

-                    if (value2.getSize() == 1) {

-                        value3 = pop();

-                        if (value3.getSize() == 1) {

-                            push(interpreter.copyOperation(insn, value2));

-                            push(interpreter.copyOperation(insn, value1));

-                            push(interpreter.copyOperation(insn, value3));

-                            push(interpreter.copyOperation(insn, value2));

-                            push(interpreter.copyOperation(insn, value1));

-                            break;

-                        }

-                    }

-                } else {

-                    value2 = pop();

-                    if (value2.getSize() == 1) {

-                        push(interpreter.copyOperation(insn, value1));

-                        push(interpreter.copyOperation(insn, value2));

-                        push(interpreter.copyOperation(insn, value1));

-                        break;

-                    }

-                }

-                throw new AnalyzerException("Illegal use of DUP2_X1");

-            case Opcodes.DUP2_X2:

-                value1 = pop();

-                if (value1.getSize() == 1) {

-                    value2 = pop();

-                    if (value2.getSize() == 1) {

-                        value3 = pop();

-                        if (value3.getSize() == 1) {

-                            value4 = pop();

-                            if (value4.getSize() == 1) {

-                                push(interpreter.copyOperation(insn, value2));

-                                push(interpreter.copyOperation(insn, value1));

-                                push(interpreter.copyOperation(insn, value4));

-                                push(interpreter.copyOperation(insn, value3));

-                                push(interpreter.copyOperation(insn, value2));

-                                push(interpreter.copyOperation(insn, value1));

-                                break;

-                            }

-                        } else {

-                            push(interpreter.copyOperation(insn, value2));

-                            push(interpreter.copyOperation(insn, value1));

-                            push(interpreter.copyOperation(insn, value3));

-                            push(interpreter.copyOperation(insn, value2));

-                            push(interpreter.copyOperation(insn, value1));

-                            break;

-                        }

-                    }

-                } else {

-                    value2 = pop();

-                    if (value2.getSize() == 1) {

-                        value3 = pop();

-                        if (value3.getSize() == 1) {

-                            push(interpreter.copyOperation(insn, value1));

-                            push(interpreter.copyOperation(insn, value3));

-                            push(interpreter.copyOperation(insn, value2));

-                            push(interpreter.copyOperation(insn, value1));

-                            break;

-                        }

-                    } else {

-                        push(interpreter.copyOperation(insn, value1));

-                        push(interpreter.copyOperation(insn, value2));

-                        push(interpreter.copyOperation(insn, value1));

-                        break;

-                    }

-                }

-                throw new AnalyzerException("Illegal use of DUP2_X2");

-            case Opcodes.SWAP:

-                value2 = pop();

-                value1 = pop();

-                if (value1.getSize() != 1 || value2.getSize() != 1) {

-                    throw new AnalyzerException("Illegal use of SWAP");

-                }

-                push(interpreter.copyOperation(insn, value2));

-                push(interpreter.copyOperation(insn, value1));

-                break;

-            case Opcodes.IADD:

-            case Opcodes.LADD:

-            case Opcodes.FADD:

-            case Opcodes.DADD:

-            case Opcodes.ISUB:

-            case Opcodes.LSUB:

-            case Opcodes.FSUB:

-            case Opcodes.DSUB:

-            case Opcodes.IMUL:

-            case Opcodes.LMUL:

-            case Opcodes.FMUL:

-            case Opcodes.DMUL:

-            case Opcodes.IDIV:

-            case Opcodes.LDIV:

-            case Opcodes.FDIV:

-            case Opcodes.DDIV:

-            case Opcodes.IREM:

-            case Opcodes.LREM:

-            case Opcodes.FREM:

-            case Opcodes.DREM:

-                value2 = pop();

-                value1 = pop();

-                push(interpreter.binaryOperation(insn, value1, value2));

-                break;

-            case Opcodes.INEG:

-            case Opcodes.LNEG:

-            case Opcodes.FNEG:

-            case Opcodes.DNEG:

-                push(interpreter.unaryOperation(insn, pop()));

-                break;

-            case Opcodes.ISHL:

-            case Opcodes.LSHL:

-            case Opcodes.ISHR:

-            case Opcodes.LSHR:

-            case Opcodes.IUSHR:

-            case Opcodes.LUSHR:

-            case Opcodes.IAND:

-            case Opcodes.LAND:

-            case Opcodes.IOR:

-            case Opcodes.LOR:

-            case Opcodes.IXOR:

-            case Opcodes.LXOR:

-                value2 = pop();

-                value1 = pop();

-                push(interpreter.binaryOperation(insn, value1, value2));

-                break;

-            case Opcodes.IINC:

-                var = ((IincInsnNode) insn).var;

-                setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));

-                break;

-            case Opcodes.I2L:

-            case Opcodes.I2F:

-            case Opcodes.I2D:

-            case Opcodes.L2I:

-            case Opcodes.L2F:

-            case Opcodes.L2D:

-            case Opcodes.F2I:

-            case Opcodes.F2L:

-            case Opcodes.F2D:

-            case Opcodes.D2I:

-            case Opcodes.D2L:

-            case Opcodes.D2F:

-            case Opcodes.I2B:

-            case Opcodes.I2C:

-            case Opcodes.I2S:

-                push(interpreter.unaryOperation(insn, pop()));

-                break;

-            case Opcodes.LCMP:

-            case Opcodes.FCMPL:

-            case Opcodes.FCMPG:

-            case Opcodes.DCMPL:

-            case Opcodes.DCMPG:

-                value2 = pop();

-                value1 = pop();

-                push(interpreter.binaryOperation(insn, value1, value2));

-                break;

-            case Opcodes.IFEQ:

-            case Opcodes.IFNE:

-            case Opcodes.IFLT:

-            case Opcodes.IFGE:

-            case Opcodes.IFGT:

-            case Opcodes.IFLE:

-                interpreter.unaryOperation(insn, pop());

-                break;

-            case Opcodes.IF_ICMPEQ:

-            case Opcodes.IF_ICMPNE:

-            case Opcodes.IF_ICMPLT:

-            case Opcodes.IF_ICMPGE:

-            case Opcodes.IF_ICMPGT:

-            case Opcodes.IF_ICMPLE:

-            case Opcodes.IF_ACMPEQ:

-            case Opcodes.IF_ACMPNE:

-                value2 = pop();

-                value1 = pop();

-                interpreter.binaryOperation(insn, value1, value2);

-                break;

-            case Opcodes.GOTO:

-                break;

-            case Opcodes.JSR:

-                push(interpreter.newOperation(insn));

-                break;

-            case Opcodes.RET:

-                break;

-            case Opcodes.TABLESWITCH:

-            case Opcodes.LOOKUPSWITCH:

-            case Opcodes.IRETURN:

-            case Opcodes.LRETURN:

-            case Opcodes.FRETURN:

-            case Opcodes.DRETURN:

-            case Opcodes.ARETURN:

-                interpreter.unaryOperation(insn, pop());

-                break;

-            case Opcodes.RETURN:

-                break;

-            case Opcodes.GETSTATIC:

-                push(interpreter.newOperation(insn));

-                break;

-            case Opcodes.PUTSTATIC:

-                interpreter.unaryOperation(insn, pop());

-                break;

-            case Opcodes.GETFIELD:

-                push(interpreter.unaryOperation(insn, pop()));

-                break;

-            case Opcodes.PUTFIELD:

-                value2 = pop();

-                value1 = pop();

-                interpreter.binaryOperation(insn, value1, value2);

-                break;

-            case Opcodes.INVOKEVIRTUAL:

-            case Opcodes.INVOKESPECIAL:

-            case Opcodes.INVOKESTATIC:

-            case Opcodes.INVOKEINTERFACE:

-                values = new ArrayList();

-                String desc = ((MethodInsnNode) insn).desc;

-                for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {

-                    values.add(0, pop());

-                }

-                if (insn.getOpcode() != Opcodes.INVOKESTATIC) {

-                    values.add(0, pop());

-                }

-                if (Type.getReturnType(desc) == Type.VOID_TYPE) {

-                    interpreter.naryOperation(insn, values);

-                } else {

-                    push(interpreter.naryOperation(insn, values));

-                }

-                break;

-            case Opcodes.NEW:

-                push(interpreter.newOperation(insn));

-                break;

-            case Opcodes.NEWARRAY:

-            case Opcodes.ANEWARRAY:

-            case Opcodes.ARRAYLENGTH:

-                push(interpreter.unaryOperation(insn, pop()));

-                break;

-            case Opcodes.ATHROW:

-                interpreter.unaryOperation(insn, pop());

-                break;

-            case Opcodes.CHECKCAST:

-            case Opcodes.INSTANCEOF:

-                push(interpreter.unaryOperation(insn, pop()));

-                break;

-            case Opcodes.MONITORENTER:

-            case Opcodes.MONITOREXIT:

-                interpreter.unaryOperation(insn, pop());

-                break;

-            case Opcodes.MULTIANEWARRAY:

-                values = new ArrayList();

-                for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {

-                    values.add(0, pop());

-                }

-                push(interpreter.naryOperation(insn, values));

-                break;

-            case Opcodes.IFNULL:

-            case Opcodes.IFNONNULL:

-                interpreter.unaryOperation(insn, pop());

-                break;

-            default:

-                throw new RuntimeException("Illegal opcode");

-        }

-    }

-

-    /**

-     * Merges this frame with the given frame.

-     * 

-     * @param frame a frame.

-     * @param interpreter the interpreter used to merge values.

-     * @return <tt>true</tt> if this frame has been changed as a result of the

-     *         merge operation, or <tt>false</tt> otherwise.

-     * @throws AnalyzerException if the frames have incompatible sizes.

-     */

-    public boolean merge(final Frame frame, final Interpreter interpreter)

-            throws AnalyzerException

-    {

-        if (top != frame.top) {

-            throw new AnalyzerException("Incompatible stack heights");

-        }

-        boolean changes = false;

-        for (int i = 0; i < locals + top; ++i) {

-            Value v = interpreter.merge(values[i], frame.values[i]);

-            if (v != values[i]) {

-                values[i] = v;

-                changes |= true;

-            }

-        }

-        return changes;

-    }

-

-    /**

-     * Merges this frame with the given frame (case of a RET instruction).

-     * 

-     * @param frame a frame

-     * @param access the local variables that have been accessed by the

-     *        subroutine to which the RET instruction corresponds.

-     * @return <tt>true</tt> if this frame has been changed as a result of the

-     *         merge operation, or <tt>false</tt> otherwise.

-     */

-    public boolean merge(final Frame frame, final boolean[] access) {

-        boolean changes = false;

-        for (int i = 0; i < locals; ++i) {

-            if (!access[i] && !values[i].equals(frame.values[i])) {

-                values[i] = frame.values[i];

-                changes = true;

-            }

-        }

-        return changes;

-    }

-

-    /**

-     * Returns a string representation of this frame.

-     * 

-     * @return a string representation of this frame.

-     */

-    public String toString() {

-        StringBuffer b = new StringBuffer();

-        for (int i = 0; i < getLocals(); ++i) {

-            b.append(getLocal(i));

-        }

-        b.append(' ');

-        for (int i = 0; i < getStackSize(); ++i) {

-            b.append(getStack(i).toString());

-        }

-        return b.toString();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Interpreter.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/Interpreter.java
deleted file mode 100644
index ec503a0..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Interpreter.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.List;

-

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.AbstractInsnNode;

-

-/**

- * A semantic bytecode interpreter. More precisely, this interpreter only

- * manages the computation of values from other values: it does not manage the

- * transfer of values to or from the stack, and to or from the local variables.

- * This separation allows a generic bytecode {@link Analyzer} to work with

- * various semantic interpreters, without needing to duplicate the code to

- * simulate the transfer of values.

- * 

- * @author Eric Bruneton

- */

-public interface Interpreter {

-

-    /**

-     * Creates a new value that represents the given type.

-     * 

-     * Called for method parameters (including <code>this</code>),

-     * exception handler variable and with <code>null</code> type 

-     * for variables reserved by long and double types.

-     * 

-     * @param type a primitive or reference type, or <tt>null</tt> to

-     *        represent an uninitialized value.

-     * @return a value that represents the given type. The size of the returned

-     *         value must be equal to the size of the given type.

-     */

-    Value newValue(Type type);

-

-    /**

-     * Interprets a bytecode instruction without arguments. This method is

-     * called for the following opcodes:

-     * 

-     * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,

-     * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,

-     * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW

-     * 

-     * @param insn the bytecode instruction to be interpreted.

-     * @return the result of the interpretation of the given instruction.

-     * @throws AnalyzerException if an error occured during the interpretation.

-     */

-    Value newOperation(AbstractInsnNode insn) throws AnalyzerException;

-

-    /**

-     * Interprets a bytecode instruction that moves a value on the stack or to

-     * or from local variables. This method is called for the following opcodes:

-     * 

-     * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,

-     * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP

-     * 

-     * @param insn the bytecode instruction to be interpreted.

-     * @param value the value that must be moved by the instruction.

-     * @return the result of the interpretation of the given instruction. The

-     *         returned value must be <tt>equal</tt> to the given value.

-     * @throws AnalyzerException if an error occured during the interpretation.

-     */

-    Value copyOperation(AbstractInsnNode insn, Value value)

-            throws AnalyzerException;

-

-    /**

-     * Interprets a bytecode instruction with a single argument. This method is

-     * called for the following opcodes:

-     * 

-     * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,

-     * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,

-     * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,

-     * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,

-     * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL

-     * 

-     * @param insn the bytecode instruction to be interpreted.

-     * @param value the argument of the instruction to be interpreted.

-     * @return the result of the interpretation of the given instruction.

-     * @throws AnalyzerException if an error occured during the interpretation.

-     */

-    Value unaryOperation(AbstractInsnNode insn, Value value)

-            throws AnalyzerException;

-

-    /**

-     * Interprets a bytecode instruction with two arguments. This method is

-     * called for the following opcodes:

-     * 

-     * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,

-     * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,

-     * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,

-     * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,

-     * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,

-     * IF_ACMPEQ, IF_ACMPNE, PUTFIELD

-     * 

-     * @param insn the bytecode instruction to be interpreted.

-     * @param value1 the first argument of the instruction to be interpreted.

-     * @param value2 the second argument of the instruction to be interpreted.

-     * @return the result of the interpretation of the given instruction.

-     * @throws AnalyzerException if an error occured during the interpretation.

-     */

-    Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2)

-            throws AnalyzerException;

-

-    /**

-     * Interprets a bytecode instruction with three arguments. This method is

-     * called for the following opcodes:

-     * 

-     * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE

-     * 

-     * @param insn the bytecode instruction to be interpreted.

-     * @param value1 the first argument of the instruction to be interpreted.

-     * @param value2 the second argument of the instruction to be interpreted.

-     * @param value3 the third argument of the instruction to be interpreted.

-     * @return the result of the interpretation of the given instruction.

-     * @throws AnalyzerException if an error occured during the interpretation.

-     */

-    Value ternaryOperation(

-        AbstractInsnNode insn,

-        Value value1,

-        Value value2,

-        Value value3) throws AnalyzerException;

-

-    /**

-     * Interprets a bytecode instruction with a variable number of arguments.

-     * This method is called for the following opcodes:

-     * 

-     * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,

-     * MULTIANEWARRAY

-     * 

-     * @param insn the bytecode instruction to be interpreted.

-     * @param values the arguments of the instruction to be interpreted.

-     * @return the result of the interpretation of the given instruction.

-     * @throws AnalyzerException if an error occured during the interpretation.

-     */

-    Value naryOperation(AbstractInsnNode insn, List values)

-            throws AnalyzerException;

-

-    /**

-     * Merges two values. The merge operation must return a value that

-     * represents both values (for instance, if the two values are two types,

-     * the merged value must be a common super type of the two types. If the two

-     * values are integer intervals, the merged value must be an interval that

-     * contains the previous ones. Likewise for other types of values).

-     * 

-     * @param v a value.

-     * @param w another value.

-     * @return the merged value. If the merged value is equal to <tt>v</tt>,

-     *         this method <i>must</i> return <tt>v</tt>.

-     */

-    Value merge(Value v, Value w);

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SimpleVerifier.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/SimpleVerifier.java
deleted file mode 100644
index 35f3ccd..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SimpleVerifier.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.List;

-

-import org.mockito.asm.Type;

-

-/**

- * An extended {@link BasicVerifier} that performs more precise verifications.

- * This verifier computes exact class types, instead of using a single "object

- * reference" type (as done in the {@link BasicVerifier}).

- * 

- * @author Eric Bruneton

- * @author Bing Ran

- */

-public class SimpleVerifier extends BasicVerifier {

-

-    /**

-     * The class that is verified.

-     */

-    private final Type currentClass;

-

-    /**

-     * The super class of the class that is verified.

-     */

-    private final Type currentSuperClass;

-

-    /**

-     * The interfaces implemented by the class that is verified.

-     */

-    private final List currentClassInterfaces;

-

-    /**

-     * If the class that is verified is an interface.

-     */

-    private final boolean isInterface;

-

-    /**

-     * Constructs a new {@link SimpleVerifier}.

-     */

-    public SimpleVerifier() {

-        this(null, null, false);

-    }

-

-    /**

-     * Constructs a new {@link SimpleVerifier} to verify a specific class. This

-     * class will not be loaded into the JVM since it may be incorrect.

-     * 

-     * @param currentClass the class that is verified.

-     * @param currentSuperClass the super class of the class that is verified.

-     * @param isInterface if the class that is verified is an interface.

-     */

-    public SimpleVerifier(

-        final Type currentClass,

-        final Type currentSuperClass,

-        final boolean isInterface)

-    {

-        this(currentClass, currentSuperClass, null, isInterface);

-    }

-

-    /**

-     * Constructs a new {@link SimpleVerifier} to verify a specific class. This

-     * class will not be loaded into the JVM since it may be incorrect.

-     * 

-     * @param currentClass the class that is verified.

-     * @param currentSuperClass the super class of the class that is verified.

-     * @param currentClassInterfaces the interfaces implemented by the class

-     *        that is verified.

-     * @param isInterface if the class that is verified is an interface.

-     */

-    public SimpleVerifier(

-        final Type currentClass,

-        final Type currentSuperClass,

-        final List currentClassInterfaces,

-        final boolean isInterface)

-    {

-        this.currentClass = currentClass;

-        this.currentSuperClass = currentSuperClass;

-        this.currentClassInterfaces = currentClassInterfaces;

-        this.isInterface = isInterface;

-    }

-

-    public Value newValue(final Type type) {

-        if (type == null) {

-            return BasicValue.UNINITIALIZED_VALUE;

-        }

-

-        boolean isArray = type.getSort() == Type.ARRAY;

-        if (isArray) {

-            switch (type.getElementType().getSort()) {

-                case Type.BOOLEAN:

-                case Type.CHAR:

-                case Type.BYTE:

-                case Type.SHORT:

-                    return new BasicValue(type);

-            }

-        }

-

-        Value v = super.newValue(type);

-        if (v == BasicValue.REFERENCE_VALUE) {

-            if (isArray) {

-                v = newValue(type.getElementType());

-                String desc = ((BasicValue) v).getType().getDescriptor();

-                for (int i = 0; i < type.getDimensions(); ++i) {

-                    desc = '[' + desc;

-                }

-                v = new BasicValue(Type.getType(desc));

-            } else {

-                v = new BasicValue(type);

-            }

-        }

-        return v;

-    }

-

-    protected boolean isArrayValue(final Value value) {

-        Type t = ((BasicValue) value).getType();

-        return t != null

-                && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);

-    }

-

-    protected Value getElementValue(final Value objectArrayValue)

-            throws AnalyzerException

-    {

-        Type arrayType = ((BasicValue) objectArrayValue).getType();

-        if (arrayType != null) {

-            if (arrayType.getSort() == Type.ARRAY) {

-                return newValue(Type.getType(arrayType.getDescriptor()

-                        .substring(1)));

-            } else if ("Lnull;".equals(arrayType.getDescriptor())) {

-                return objectArrayValue;

-            }

-        }

-        throw new Error("Internal error");

-    }

-

-    protected boolean isSubTypeOf(final Value value, final Value expected) {

-        Type expectedType = ((BasicValue) expected).getType();

-        Type type = ((BasicValue) value).getType();

-        switch (expectedType.getSort()) {

-            case Type.INT:

-            case Type.FLOAT:

-            case Type.LONG:

-            case Type.DOUBLE:

-                return type == expectedType;

-            case Type.ARRAY:

-            case Type.OBJECT:

-                if ("Lnull;".equals(type.getDescriptor())) {

-                    return true;

-                } else if (type.getSort() == Type.OBJECT

-                        || type.getSort() == Type.ARRAY)

-                {

-                    return isAssignableFrom(expectedType, type);

-                } else {

-                    return false;

-                }

-            default:

-                throw new Error("Internal error");

-        }

-    }

-

-    public Value merge(final Value v, final Value w) {

-        if (!v.equals(w)) {

-            Type t = ((BasicValue) v).getType();

-            Type u = ((BasicValue) w).getType();

-            if (t != null

-                    && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY))

-            {

-                if (u != null

-                        && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY))

-                {

-                    if ("Lnull;".equals(t.getDescriptor())) {

-                        return w;

-                    }

-                    if ("Lnull;".equals(u.getDescriptor())) {

-                        return v;

-                    }

-                    if (isAssignableFrom(t, u)) {

-                        return v;

-                    }

-                    if (isAssignableFrom(u, t)) {

-                        return w;

-                    }

-                    // TODO case of array classes of the same dimension

-                    // TODO should we look also for a common super interface?

-                    // problem: there may be several possible common super

-                    // interfaces

-                    do {

-                        if (t == null || isInterface(t)) {

-                            return BasicValue.REFERENCE_VALUE;

-                        }

-                        t = getSuperClass(t);

-                        if (isAssignableFrom(t, u)) {

-                            return newValue(t);

-                        }

-                    } while (true);

-                }

-            }

-            return BasicValue.UNINITIALIZED_VALUE;

-        }

-        return v;

-    }

-

-    protected boolean isInterface(final Type t) {

-        if (currentClass != null && t.equals(currentClass)) {

-            return isInterface;

-        }

-        return getClass(t).isInterface();

-    }

-

-    protected Type getSuperClass(final Type t) {

-        if (currentClass != null && t.equals(currentClass)) {

-            return currentSuperClass;

-        }

-        Class c = getClass(t).getSuperclass();

-        return c == null ? null : Type.getType(c);

-    }

-

-    protected boolean isAssignableFrom(final Type t, final Type u) {

-        if (t.equals(u)) {

-            return true;

-        }

-        if (currentClass != null && t.equals(currentClass)) {

-            if (getSuperClass(u) == null) {

-                return false;

-            } else {

-                return isAssignableFrom(t, getSuperClass(u));

-            }

-        }

-        if (currentClass != null && u.equals(currentClass)) {

-            if (isAssignableFrom(t, currentSuperClass)) {

-                return true;

-            }

-            if (currentClassInterfaces != null) {

-                for (int i = 0; i < currentClassInterfaces.size(); ++i) {

-                    Type v = (Type) currentClassInterfaces.get(i);

-                    if (isAssignableFrom(t, v)) {

-                        return true;

-                    }

-                }

-            }

-            return false;

-        }

-        return getClass(t).isAssignableFrom(getClass(u));

-    }

-

-    protected Class getClass(final Type t) {

-        try {

-            if (t.getSort() == Type.ARRAY) {

-                return Class.forName(t.getDescriptor().replace('/', '.'));

-            }

-            return Class.forName(t.getClassName());

-        } catch (ClassNotFoundException e) {

-            throw new RuntimeException(e.toString());

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SmallSet.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/SmallSet.java
deleted file mode 100644
index ed96155..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SmallSet.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.AbstractSet;

-import java.util.HashSet;

-import java.util.Iterator;

-import java.util.Set;

-

-/**

- * A set of at most two elements.

- * 

- * @author Eric Bruneton

- */

-class SmallSet extends AbstractSet implements Iterator {

-

-    // if e1 is null, e2 must be null; otherwise e2 must be different from e1

-

-    Object e1, e2;

-

-    static final Set EMPTY_SET = new SmallSet(null, null);

-

-    SmallSet(final Object e1, final Object e2) {

-        this.e1 = e1;

-        this.e2 = e2;

-    }

-

-    // -------------------------------------------------------------------------

-    // Implementation of inherited abstract methods

-    // -------------------------------------------------------------------------

-

-    public Iterator iterator() {

-        return new SmallSet(e1, e2);

-    }

-

-    public int size() {

-        return e1 == null ? 0 : (e2 == null ? 1 : 2);

-    }

-

-    // -------------------------------------------------------------------------

-    // Implementation of the Iterator interface

-    // -------------------------------------------------------------------------

-

-    public boolean hasNext() {

-        return e1 != null;

-    }

-

-    public Object next() {

-        Object e = e1;

-        e1 = e2;

-        e2 = null;

-        return e;

-    }

-

-    public void remove() {

-    }

-

-    // -------------------------------------------------------------------------

-    // Utility methods

-    // -------------------------------------------------------------------------

-

-    Set union(final SmallSet s) {

-        if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {

-            return this; // if the two sets are equal, return this

-        }

-        if (s.e1 == null) {

-            return this; // if s is empty, return this

-        }

-        if (e1 == null) {

-            return s; // if this is empty, return s

-        }

-        if (s.e2 == null) { // s contains exactly one element

-            if (e2 == null) {

-                return new SmallSet(e1, s.e1); // necessarily e1 != s.e1

-            } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this

-                return this;

-            }

-        }

-        if (e2 == null) { // this contains exactly one element

-            // if (s.e2 == null) { // cannot happen

-            // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1

-            // } else

-            if (e1 == s.e1 || e1 == s.e2) { // this in included in s

-                return s;

-            }

-        }

-        // here we know that there are at least 3 distinct elements

-        HashSet r = new HashSet(4);

-        r.add(e1);

-        if (e2 != null) {

-            r.add(e2);

-        }

-        r.add(s.e1);

-        if (s.e2 != null) {

-            r.add(s.e2);

-        }

-        return r;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SourceInterpreter.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/SourceInterpreter.java
deleted file mode 100644
index 1a9e59b..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SourceInterpreter.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.HashSet;

-import java.util.List;

-import java.util.Set;

-

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.AbstractInsnNode;

-import org.mockito.asm.tree.FieldInsnNode;

-import org.mockito.asm.tree.LdcInsnNode;

-import org.mockito.asm.tree.MethodInsnNode;

-

-/**

- * An {@link Interpreter} for {@link SourceValue} values.

- * 

- * @author Eric Bruneton

- */

-public class SourceInterpreter implements Opcodes, Interpreter {

-

-    public Value newValue(final Type type) {

-        return new SourceValue(type == null ? 1 : type.getSize());

-    }

-

-    public Value newOperation(final AbstractInsnNode insn) {

-        int size;

-        switch (insn.getOpcode()) {

-            case LCONST_0:

-            case LCONST_1:

-            case DCONST_0:

-            case DCONST_1:

-                size = 2;

-                break;

-            case LDC:

-                Object cst = ((LdcInsnNode) insn).cst;

-                size = cst instanceof Long || cst instanceof Double ? 2 : 1;

-                break;

-            case GETSTATIC:

-                size = Type.getType(((FieldInsnNode) insn).desc).getSize();

-                break;

-            default:

-                size = 1;

-        }

-        return new SourceValue(size, insn);

-    }

-

-    public Value copyOperation(final AbstractInsnNode insn, final Value value) {

-        return new SourceValue(value.getSize(), insn);

-    }

-

-    public Value unaryOperation(final AbstractInsnNode insn, final Value value)

-    {

-        int size;

-        switch (insn.getOpcode()) {

-            case LNEG:

-            case DNEG:

-            case I2L:

-            case I2D:

-            case L2D:

-            case F2L:

-            case F2D:

-            case D2L:

-                size = 2;

-                break;

-            case GETFIELD:

-                size = Type.getType(((FieldInsnNode) insn).desc).getSize();

-                break;

-            default:

-                size = 1;

-        }

-        return new SourceValue(size, insn);

-    }

-

-    public Value binaryOperation(

-        final AbstractInsnNode insn,

-        final Value value1,

-        final Value value2)

-    {

-        int size;

-        switch (insn.getOpcode()) {

-            case LALOAD:

-            case DALOAD:

-            case LADD:

-            case DADD:

-            case LSUB:

-            case DSUB:

-            case LMUL:

-            case DMUL:

-            case LDIV:

-            case DDIV:

-            case LREM:

-            case DREM:

-            case LSHL:

-            case LSHR:

-            case LUSHR:

-            case LAND:

-            case LOR:

-            case LXOR:

-                size = 2;

-                break;

-            default:

-                size = 1;

-        }

-        return new SourceValue(size, insn);

-    }

-

-    public Value ternaryOperation(

-        final AbstractInsnNode insn,

-        final Value value1,

-        final Value value2,

-        final Value value3)

-    {

-        return new SourceValue(1, insn);

-    }

-

-    public Value naryOperation(final AbstractInsnNode insn, final List values) {

-        int size;

-        if (insn.getOpcode() == MULTIANEWARRAY) {

-            size = 1;

-        } else {

-            size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();

-        }

-        return new SourceValue(size, insn);

-    }

-

-    public Value merge(final Value v, final Value w) {

-        SourceValue dv = (SourceValue) v;

-        SourceValue dw = (SourceValue) w;

-        if (dv.insns instanceof SmallSet && dw.insns instanceof SmallSet) {

-            Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns);

-            if (s == dv.insns && dv.size == dw.size) {

-                return v;

-            } else {

-                return new SourceValue(Math.min(dv.size, dw.size), s);

-            }

-        }

-        if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) {

-            Set s = new HashSet();

-            s.addAll(dv.insns);

-            s.addAll(dw.insns);

-            return new SourceValue(Math.min(dv.size, dw.size), s);

-        }

-        return v;

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SourceValue.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/SourceValue.java
deleted file mode 100644
index 9fd3c4f..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/SourceValue.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.Set;

-

-import org.mockito.asm.tree.AbstractInsnNode;

-

-/**

- * A {@link Value} that is represented by its type in a two types type system.

- * This type system distinguishes the ONEWORD and TWOWORDS types.

- * 

- * @author Eric Bruneton

- */

-public class SourceValue implements Value {

-

-    /**

-     * The size of this value.

-     */

-    public final int size;

-

-    /**

-     * The instructions that can produce this value. For example, for the Java

-     * code below, the instructions that can produce the value of <tt>i</tt>

-     * at line 5 are the txo ISTORE instructions at line 1 and 3:

-     * 

-     * <pre>

-     * 1: i = 0;

-     * 2: if (...) {

-     * 3:   i = 1;

-     * 4: }

-     * 5: return i;

-     * </pre>

-     * 

-     * This field is a set of {@link AbstractInsnNode} objects.

-     */

-    public final Set insns;

-

-    public SourceValue(final int size) {

-        this(size, SmallSet.EMPTY_SET);

-    }

-

-    public SourceValue(final int size, final AbstractInsnNode insn) {

-        this.size = size;

-        this.insns = new SmallSet(insn, null);

-    }

-

-    public SourceValue(final int size, final Set insns) {

-        this.size = size;

-        this.insns = insns;

-    }

-

-    public int getSize() {

-        return size;

-    }

-

-    public boolean equals(final Object value) {

-        if (!(value instanceof SourceValue)) {

-        	return false;

-        }

-        SourceValue v = (SourceValue) value;

-        return size == v.size && insns.equals(v.insns);

-    }

-

-    public int hashCode() {

-        return insns.hashCode();

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Subroutine.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/Subroutine.java
deleted file mode 100644
index d0ce432..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Subroutine.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-import java.util.ArrayList;

-import java.util.List;

-

-import org.mockito.asm.tree.JumpInsnNode;

-import org.mockito.asm.tree.LabelNode;

-

-/**

- * A method subroutine (corresponds to a JSR instruction).

- * 

- * @author Eric Bruneton

- */

-class Subroutine {

-

-    LabelNode start;

-

-    boolean[] access;

-

-    List callers;

-

-    private Subroutine() {

-    }

-

-    Subroutine(

-        final LabelNode start,

-        final int maxLocals,

-        final JumpInsnNode caller)

-    {

-        this.start = start;

-        this.access = new boolean[maxLocals];

-        this.callers = new ArrayList();

-        callers.add(caller);

-    }

-

-    public Subroutine copy() {

-        Subroutine result = new Subroutine();

-        result.start = start;

-        result.access = new boolean[access.length];

-        System.arraycopy(access, 0, result.access, 0, access.length);

-        result.callers = new ArrayList(callers);

-        return result;

-    }

-

-    public boolean merge(final Subroutine subroutine) throws AnalyzerException {

-        boolean changes = false;

-        for (int i = 0; i < access.length; ++i) {

-            if (subroutine.access[i] && !access[i]) {

-                access[i] = true;

-                changes = true;

-            }

-        }

-        if (subroutine.start == start) {

-            for (int i = 0; i < subroutine.callers.size(); ++i) {

-                Object caller = subroutine.callers.get(i);

-                if (!callers.contains(caller)) {

-                    callers.add(caller);

-                    changes = true;

-                }

-            }

-        }

-        return changes;

-    }

-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Value.java b/cglib-and-asm/src/org/mockito/asm/tree/analysis/Value.java
deleted file mode 100644
index 83d3017..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/Value.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.tree.analysis;

-

-/**

- * An immutable symbolic value for semantic interpretation of bytecode.

- * 

- * @author Eric Bruneton

- */

-public interface Value {

-

-    /**

-     * Returns the size of this value in words.

-     * 

-     * @return either 1 or 2.

-     */

-    int getSize();

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/analysis/package.html b/cglib-and-asm/src/org/mockito/asm/tree/analysis/package.html
deleted file mode 100644
index 46b6c26..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/analysis/package.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<html>

-<!--

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2005 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

--->

-<body>

-

-<p>

-Provides a framework for static code analysis based on the asm.tree package.

-</p>

-

-<p>

-Basic usage:

-</p>

-

-<pre>

-ClassReader cr = new ClassReader(bytecode);

-ClassNode cn = new ClassNode();

-cr.accept(cn, ClassReader.SKIP_DEBUG);

-

-List methods = cn.methods;

-for (int i = 0; i < methods.size(); ++i) {

-    MethodNode method = (MethodNode) methods.get(i);

-    if (method.instructions.size() > 0) {

-        Analyzer a = new Analyzer(new BasicInterpreter());

-        a.analyze(cn.name, method);

-        Frame[] frames = a.getFrames();

-        // Elements of the frames arrray now contains info for each instruction 

-        // from the analyzed method. BasicInterpreter creates BasicValue, that

-        // is using simplified type system that distinguishes the UNINITIALZED, 

-        // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.

-        ...

-    }

-}   

-</pre>

-

-<p>

-@since ASM 1.4.3

-</p>

-

-</body>

-</html>

diff --git a/cglib-and-asm/src/org/mockito/asm/tree/package.html b/cglib-and-asm/src/org/mockito/asm/tree/package.html
deleted file mode 100644
index 92ea013..0000000
--- a/cglib-and-asm/src/org/mockito/asm/tree/package.html
+++ /dev/null
@@ -1,192 +0,0 @@
-<html>

-<!--

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2005 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

--->

-<body>

-  

-<p>  

-Provides an ASM visitor that constructs a tree representation of the

-classes it visits. This class adapter can be useful to implement "complex"

-class manipulation operations, i.e., operations that would be very hard to

-implement without using a tree representation (such as optimizing the number

-of local variables used by a method).

-</p>

-  

-<p>

-However, this class adapter has a cost: it makes ASM bigger and slower. Indeed

-it requires more than twenty new classes, and multiplies the time needed to

-transform a class by almost two (it is almost two times faster to read, "modify"

-and write a class with a ClassAdapter than with a ClassNode). This is why

-this package is bundled in an optional <tt>asm-tree.jar</tt> library that

-is separated from (but requires) the <tt>asm.jar</tt> library, which contains

-the core ASM framework. This is also why <i><font color="red">it is recommended

-not to use this class adapter when it is possible</font></i>.

-</p>

-

-<p>

-The root class is the ClassNode, that can be created from existing bytecode. For example:

-</p>

-  

-<pre>

-  ClassReader cr = new ClassReader(source);

-  ClassNode cn = new ClassNode();

-  cr.accept(cn, true);

-</pre>

-

-<p>

-Now content of ClassNode can be modified and then

-serialized back into bytecode:

-</p>

-

-<pre>

-  ClassWriter cw = new ClassWriter(true);

-  cn.accept(cw);

-</pre>  

-

-<p>

-Using simple ClassAdapter it is possible to create MethodNode instances per-method.

-In this example MethodNode is acting as a buffer that is flushed out at visitEnd() call:

-</p>

-

-<pre>

-  ClassReader cr = new ClassReader(source);

-  ClassWriter cw = new ClassWriter();

-  ClassAdapter ca = new ClassAdapter(cw) {

-      public MethodVisitor visitMethod(int access, String name, 

-          String desc, String signature, String[] exceptions) {

-        final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);

-        MethodNode mn = new MethodNode(access, name, desc, signature, exceptions) {

-            public void visitEnd() {

-              // transform or analyze method code using tree API

-              accept(mv);

-            }

-          };

-      }

-    };

-  cr.accept(ca, true);

-</pre>

-

-<p>  

-Several strategies can be used to construct method code from scratch. The first

-option is to create a MethodNode, and then create XXXInsnNode instances and 

-add them to the instructions list:

-</p>

-

-<pre>

-MethodNode m = new MethodNode(...);

-m.instructions.add(new VarInsnNode(ALOAD, 0));

-...

-</pre>

-

-<p>

-Alternatively, you can use the fact that MethodNode is a MethodVisitor, and use

-that to create the XXXInsnNode and add them to the instructions list through

-the standard MethodVisitor interface:

-</p>

-

-<pre>

-MethodNode m = new MethodNode(...);

-m.visitVarInsn(ALOAD, 0);

-...

-</pre>

-

-<p>

-If you cannot generate all the instructions in sequential order, i.e. if you 

-need to save some pointer in the instruction list and then insert instructions

-at that place after other instructions have been generated, you can use InsnList 

-methods insert() and insertBefore() to insert instructions at saved pointer.

-</p>

-

-<pre>

-MethodNode m = new MethodNode(...);

-m.visitVarInsn(ALOAD, 0);

-AbstractInsnNode ptr = m.instructions.getLast();

-m.visitVarInsn(ALOAD, 1);

-// inserts an instruction between ALOAD 0 and ALOAD 1

-m.instructions.insert(ptr, new VarInsnNode(ALOAD, 0));

-...

-</pre>

-

-<p>

-If you need to insert instructions while iterating over an existing instruction 

-list, you can also use several strategies. The first one is to use a 

-ListIterator over the instruction list:

-</p>

-

-<pre>

-ListIterator it = m.instructions.iterator();

-while (it.hasNext()) {

-    AbstractInsnNode n = (AbstractInsnNode) it.next();

-    if (...) {

-        it.add(new VarInsnNode(ALOAD, 0));

-    }

-}

-</pre>

-

-<p>

-It is also possible to convert instruction list into the array and iterate trough

-array elements:

-</p>

-

-<pre>

-AbstractInsnNode[] insns = m.instructions.toArray();

-for(int i = 0; i&lt;insns.length; i++) {

-    AbstractInsnNode n = insns[i];

-    if (...) {

-        m.instructions.insert(n, new VarInsnNode(ALOAD, 0));

-    }

-}

-</pre>

-

-<p>

-If you want to insert these instructions through the MethodVisitor interface,

-you can use another instance of MethodNode as a MethodVisitor and then 

-insert instructions collected by that instance into the instruction list. 

-For example:

-</p>

-

-<pre>

-AbstractInsnNode[] insns = m.instructions.toArray();

-for(int i = 0; i&lt;insns.length; i++) {

-    AbstractInsnNode n = insns[i];

-    if (...) {

-        MethodNode mn = new MethodNode();

-        mn.visitVarInsn(ALOAD, 0);

-        mn.visitVarInsn(ALOAD, 1);

-        m.instructions.insert(n, mn.instructions);

-    }

-}

-</pre>

-

-<p>  

-@since ASM 1.3.3

-</p>

-    

-</body>

-</html>

diff --git a/cglib-and-asm/src/org/mockito/asm/util/ASMifiable.java b/cglib-and-asm/src/org/mockito/asm/util/ASMifiable.java
deleted file mode 100644
index c21842e..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/ASMifiable.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import java.util.Map;

-

-/**

- * An attribute that can print the ASM code to create an equivalent attribute.

- * 

- * Implementation should print the ASM code that generates attribute data

- * structures for current attribute state.

- * 

- * @author Eugene Kuleshov

- */

-public interface ASMifiable {

-

-    /**

-     * Prints the ASM code to create an attribute equal to this attribute.

-     * 

-     * @param buf A buffer used for printing Java code.

-     * @param varName name of the variable in a printed code used to store

-     *        attribute instance.

-     * @param labelNames map of label instances to their names.

-     */

-    void asmify(StringBuffer buf, String varName, Map labelNames);

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/ASMifierAbstractVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/ASMifierAbstractVisitor.java
deleted file mode 100644
index 7640535..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/ASMifierAbstractVisitor.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.Type;

-

-import java.util.Map;

-

-/**

- * An abstract ASMifier visitor.

- * 

- * @author Eric Bruneton

- */

-public class ASMifierAbstractVisitor extends AbstractVisitor {

-

-    /**

-     * The name of the variable for this visitor in the produced code.

-     */

-    protected String name;

-

-    /**

-     * The label names. This map associates String values to Label keys. It is

-     * used only in ASMifierMethodVisitor.

-     */

-    Map labelNames;

-

-    /**

-     * Constructs a new {@link ASMifierAbstractVisitor}.

-     * 

-     * @param name the name of the variable for this visitor in the produced

-     *        code.

-     */

-    protected ASMifierAbstractVisitor(final String name) {

-        this.name = name;

-    }

-

-    /**

-     * Prints the ASM code that generates the given annotation.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values.

-     */

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        buf.setLength(0);

-        buf.append("{\n")

-                .append("av0 = ")

-                .append(name)

-                .append(".visitAnnotation(");

-        appendConstant(desc);

-        buf.append(", ").append(visible).append(");\n");

-        text.add(buf.toString());

-        ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);

-        text.add(av.getText());

-        text.add("}\n");

-        return av;

-    }

-

-    /**

-     * Prints the ASM code that generates the given attribute.

-     * 

-     * @param attr an attribute.

-     */

-    public void visitAttribute(final Attribute attr) {

-        buf.setLength(0);

-        buf.append("// ATTRIBUTE ").append(attr.type).append('\n');

-        if (attr instanceof ASMifiable) {

-            buf.append("{\n");

-            ((ASMifiable) attr).asmify(buf, "attr", labelNames);

-            buf.append(name).append(".visitAttribute(attr);\n");

-            buf.append("}\n");

-        }

-        text.add(buf.toString());

-    }

-

-    /**

-     * Prints the ASM code to end the visit.

-     */

-    public void visitEnd() {

-        buf.setLength(0);

-        buf.append(name).append(".visitEnd();\n");

-        text.add(buf.toString());

-    }

-

-    /**

-     * Appends a string representation of the given constant to the given

-     * buffer.

-     * 

-     * @param cst an {@link Integer}, {@link Float}, {@link Long},

-     *        {@link Double} or {@link String} object. May be <tt>null</tt>.

-     */

-    void appendConstant(final Object cst) {

-        appendConstant(buf, cst);

-    }

-

-    /**

-     * Appends a string representation of the given constant to the given

-     * buffer.

-     * 

-     * @param buf a string buffer.

-     * @param cst an {@link Integer}, {@link Float}, {@link Long},

-     *        {@link Double} or {@link String} object. May be <tt>null</tt>.

-     */

-    static void appendConstant(final StringBuffer buf, final Object cst) {

-        if (cst == null) {

-            buf.append("null");

-        } else if (cst instanceof String) {

-            appendString(buf, (String) cst);

-        } else if (cst instanceof Type) {

-            buf.append("Type.getType(\"");

-            buf.append(((Type) cst).getDescriptor());

-            buf.append("\")");

-        } else if (cst instanceof Byte) {

-            buf.append("new Byte((byte)").append(cst).append(')');

-        } else if (cst instanceof Boolean) {

-            buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" : "Boolean.FALSE");

-        } else if (cst instanceof Short) {

-            buf.append("new Short((short)").append(cst).append(')');

-        } else if (cst instanceof Character) {

-            int c = ((Character) cst).charValue();

-            buf.append("new Character((char)").append(c).append(')');

-        } else if (cst instanceof Integer) {

-            buf.append("new Integer(").append(cst).append(')');

-        } else if (cst instanceof Float) {

-            buf.append("new Float(\"").append(cst).append("\")");

-        } else if (cst instanceof Long) {

-            buf.append("new Long(").append(cst).append("L)");

-        } else if (cst instanceof Double) {

-            buf.append("new Double(\"").append(cst).append("\")");

-        } else if (cst instanceof byte[]) {

-            byte[] v = (byte[]) cst;

-            buf.append("new byte[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append(v[i]);

-            }

-            buf.append('}');

-        } else if (cst instanceof boolean[]) {

-            boolean[] v = (boolean[]) cst;

-            buf.append("new boolean[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append(v[i]);

-            }

-            buf.append('}');

-        } else if (cst instanceof short[]) {

-            short[] v = (short[]) cst;

-            buf.append("new short[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);

-            }

-            buf.append('}');

-        } else if (cst instanceof char[]) {

-            char[] v = (char[]) cst;

-            buf.append("new char[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",")

-                        .append("(char)")

-                        .append((int) v[i]);

-            }

-            buf.append('}');

-        } else if (cst instanceof int[]) {

-            int[] v = (int[]) cst;

-            buf.append("new int[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append(v[i]);

-            }

-            buf.append('}');

-        } else if (cst instanceof long[]) {

-            long[] v = (long[]) cst;

-            buf.append("new long[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append(v[i]).append('L');

-            }

-            buf.append('}');

-        } else if (cst instanceof float[]) {

-            float[] v = (float[]) cst;

-            buf.append("new float[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append(v[i]).append('f');

-            }

-            buf.append('}');

-        } else if (cst instanceof double[]) {

-            double[] v = (double[]) cst;

-            buf.append("new double[] {");

-            for (int i = 0; i < v.length; i++) {

-                buf.append(i == 0 ? "" : ",").append(v[i]).append('d');

-            }

-            buf.append('}');

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/ASMifierAnnotationVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/ASMifierAnnotationVisitor.java
deleted file mode 100644
index dc5e01e..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/ASMifierAnnotationVisitor.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-

-/**

- * An {@link AnnotationVisitor} that prints the ASM code that generates the

- * annotations it visits.

- * 

- * @author Eric Bruneton

- */

-public class ASMifierAnnotationVisitor extends AbstractVisitor implements

-        AnnotationVisitor

-{

-

-    /**

-     * Identifier of the annotation visitor variable in the produced code.

-     */

-    protected final int id;

-

-    /**

-     * Constructs a new {@link ASMifierAnnotationVisitor}.

-     * 

-     * @param id identifier of the annotation visitor variable in the produced

-     *        code.

-     */

-    public ASMifierAnnotationVisitor(final int id) {

-        this.id = id;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the AnnotationVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(final String name, final Object value) {

-        buf.setLength(0);

-        buf.append("av").append(id).append(".visit(");

-        ASMifierAbstractVisitor.appendConstant(buf, name);

-        buf.append(", ");

-        ASMifierAbstractVisitor.appendConstant(buf, value);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitEnum(

-        final String name,

-        final String desc,

-        final String value)

-    {

-        buf.setLength(0);

-        buf.append("av").append(id).append(".visitEnum(");

-        ASMifierAbstractVisitor.appendConstant(buf, name);

-        buf.append(", ");

-        ASMifierAbstractVisitor.appendConstant(buf, desc);

-        buf.append(", ");

-        ASMifierAbstractVisitor.appendConstant(buf, value);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append("{\n");

-        buf.append("AnnotationVisitor av").append(id + 1).append(" = av");

-        buf.append(id).append(".visitAnnotation(");

-        ASMifierAbstractVisitor.appendConstant(buf, name);

-        buf.append(", ");

-        ASMifierAbstractVisitor.appendConstant(buf, desc);

-        buf.append(");\n");

-        text.add(buf.toString());

-        ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(id + 1);

-        text.add(av.getText());

-        text.add("}\n");

-        return av;

-    }

-

-    public AnnotationVisitor visitArray(final String name) {

-        buf.setLength(0);

-        buf.append("{\n");

-        buf.append("AnnotationVisitor av").append(id + 1).append(" = av");

-        buf.append(id).append(".visitArray(");

-        ASMifierAbstractVisitor.appendConstant(buf, name);

-        buf.append(");\n");

-        text.add(buf.toString());

-        ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(id + 1);

-        text.add(av.getText());

-        text.add("}\n");

-        return av;

-    }

-

-    public void visitEnd() {

-        buf.setLength(0);

-        buf.append("av").append(id).append(".visitEnd();\n");

-        text.add(buf.toString());

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/ASMifierClassVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/ASMifierClassVisitor.java
deleted file mode 100644
index abf4a59..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/ASMifierClassVisitor.java
+++ /dev/null
@@ -1,575 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import java.io.FileInputStream;

-import java.io.PrintWriter;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.ClassReader;

-import org.mockito.asm.ClassVisitor;

-import org.mockito.asm.FieldVisitor;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-/**

- * A {@link ClassVisitor} that prints the ASM code that generates the classes it

- * visits. This class visitor can be used to quickly write ASM code to generate

- * some given bytecode: <ul> <li>write the Java source code equivalent to the

- * bytecode you want to generate;</li> <li>compile it with <tt>javac</tt>;</li>

- * <li>make a {@link ASMifierClassVisitor} visit this compiled class (see the

- * {@link #main main} method);</li> <li>edit the generated source code, if

- * necessary.</li> </ul> The source code printed when visiting the

- * <tt>Hello</tt> class is the following: <p> <blockquote>

- * 

- * <pre>

- * import org.mockito.asm.*;

- *

- * public class HelloDump implements Opcodes {

- *

- *     public static byte[] dump() throws Exception {

- *

- *         ClassWriter cw = new ClassWriter(0);

- *         FieldVisitor fv;

- *         MethodVisitor mv;

- *         AnnotationVisitor av0;

- *

- *         cw.visit(49,

- *                 ACC_PUBLIC + ACC_SUPER,

- *                 &quot;Hello&quot;,

- *                 null,

- *                 &quot;java/lang/Object&quot;,

- *                 null);

- *

- *         cw.visitSource(&quot;Hello.java&quot;, null);

- *

- *         {

- *             mv = cw.visitMethod(ACC_PUBLIC, &quot;&lt;init&gt;&quot;, &quot;()V&quot;, null, null);

- *             mv.visitVarInsn(ALOAD, 0);

- *             mv.visitMethodInsn(INVOKESPECIAL,

- *                     &quot;java/lang/Object&quot;,

- *                     &quot;&lt;init&gt;&quot;,

- *                     &quot;()V&quot;);

- *             mv.visitInsn(RETURN);

- *             mv.visitMaxs(1, 1);

- *             mv.visitEnd();

- *         }

- *         {

- *             mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,

- *                     &quot;main&quot;,

- *                     &quot;([Ljava/lang/String;)V&quot;,

- *                     null,

- *                     null);

- *             mv.visitFieldInsn(GETSTATIC,

- *                     &quot;java/lang/System&quot;,

- *                     &quot;out&quot;,

- *                     &quot;Ljava/io/PrintStream;&quot;);

- *             mv.visitLdcInsn(&quot;hello&quot;);

- *             mv.visitMethodInsn(INVOKEVIRTUAL,

- *                     &quot;java/io/PrintStream&quot;,

- *                     &quot;println&quot;,

- *                     &quot;(Ljava/lang/String;)V&quot;);

- *             mv.visitInsn(RETURN);

- *             mv.visitMaxs(2, 1);

- *             mv.visitEnd();

- *         }

- *         cw.visitEnd();

- *

- *         return cw.toByteArray();

- *     }

- * }

- *

- * </pre>

- * 

- * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>

- * 

- * <pre>

- * public class Hello {

- *

- *     public static void main(String[] args) {

- *         System.out.println(&quot;hello&quot;);

- *     }

- * }

- * </pre>

- * 

- * </blockquote>

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public class ASMifierClassVisitor extends ASMifierAbstractVisitor implements

-        ClassVisitor

-{

-

-    /**

-     * Pseudo access flag used to distinguish class access flags.

-     */

-    private static final int ACCESS_CLASS = 262144;

-

-    /**

-     * Pseudo access flag used to distinguish field access flags.

-     */

-    private static final int ACCESS_FIELD = 524288;

-

-    /**

-     * Pseudo access flag used to distinguish inner class flags.

-     */

-    private static final int ACCESS_INNER = 1048576;

-

-    /**

-     * The print writer to be used to print the class.

-     */

-    protected final PrintWriter pw;

-

-    /**

-     * Prints the ASM source code to generate the given class to the standard

-     * output. <p> Usage: ASMifierClassVisitor [-debug] &lt;fully qualified

-     * class name or class file name&gt;

-     * 

-     * @param args the command line arguments.

-     * 

-     * @throws Exception if the class cannot be found, or if an IO exception

-     *         occurs.

-     */

-    public static void main(final String[] args) throws Exception {

-        int i = 0;

-        int flags = ClassReader.SKIP_DEBUG;

-

-        boolean ok = true;

-        if (args.length < 1 || args.length > 2) {

-            ok = false;

-        }

-        if (ok && "-debug".equals(args[0])) {

-            i = 1;

-            flags = 0;

-            if (args.length != 2) {

-                ok = false;

-            }

-        }

-        if (!ok) {

-            System.err.println("Prints the ASM code to generate the given class.");

-            System.err.println("Usage: ASMifierClassVisitor [-debug] "

-                    + "<fully qualified class name or class file name>");

-            return;

-        }

-        ClassReader cr;

-        if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1

-                || args[i].indexOf('/') > -1)

-        {

-            cr = new ClassReader(new FileInputStream(args[i]));

-        } else {

-            cr = new ClassReader(args[i]);

-        }

-        cr.accept(new ASMifierClassVisitor(new PrintWriter(System.out)),

-                getDefaultAttributes(),

-                flags);

-    }

-

-    /**

-     * Constructs a new {@link ASMifierClassVisitor} object.

-     * 

-     * @param pw the print writer to be used to print the class.

-     */

-    public ASMifierClassVisitor(final PrintWriter pw) {

-        super("cw");

-        this.pw = pw;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the ClassVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(

-        final int version,

-        final int access,

-        final String name,

-        final String signature,

-        final String superName,

-        final String[] interfaces)

-    {

-        String simpleName;

-        int n = name.lastIndexOf('/');

-        if (n == -1) {

-            simpleName = name;

-        } else {

-            text.add("package asm." + name.substring(0, n).replace('/', '.')

-                    + ";\n");

-            simpleName = name.substring(n + 1);

-        }

-        text.add("import java.util.*;\n");

-        text.add("import org.mockito.asm.*;\n");

-        text.add("import org.mockito.asm.attrs.*;\n");

-        text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");

-        text.add("public static byte[] dump () throws Exception {\n\n");

-        text.add("ClassWriter cw = new ClassWriter(0);\n");

-        text.add("FieldVisitor fv;\n");

-        text.add("MethodVisitor mv;\n");

-        text.add("AnnotationVisitor av0;\n\n");

-

-        buf.setLength(0);

-        buf.append("cw.visit(");

-        switch (version) {

-            case Opcodes.V1_1:

-                buf.append("V1_1");

-                break;

-            case Opcodes.V1_2:

-                buf.append("V1_2");

-                break;

-            case Opcodes.V1_3:

-                buf.append("V1_3");

-                break;

-            case Opcodes.V1_4:

-                buf.append("V1_4");

-                break;

-            case Opcodes.V1_5:

-                buf.append("V1_5");

-                break;

-            case Opcodes.V1_6:

-                buf.append("V1_6");

-                break;

-            default:

-                buf.append(version);

-                break;

-        }

-        buf.append(", ");

-        appendAccess(access | ACCESS_CLASS);

-        buf.append(", ");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(signature);

-        buf.append(", ");

-        appendConstant(superName);

-        buf.append(", ");

-        if (interfaces != null && interfaces.length > 0) {

-            buf.append("new String[] {");

-            for (int i = 0; i < interfaces.length; ++i) {

-                buf.append(i == 0 ? " " : ", ");

-                appendConstant(interfaces[i]);

-            }

-            buf.append(" }");

-        } else {

-            buf.append("null");

-        }

-        buf.append(");\n\n");

-        text.add(buf.toString());

-    }

-

-    public void visitSource(final String file, final String debug) {

-        buf.setLength(0);

-        buf.append("cw.visitSource(");

-        appendConstant(file);

-        buf.append(", ");

-        appendConstant(debug);

-        buf.append(");\n\n");

-        text.add(buf.toString());

-    }

-

-    public void visitOuterClass(

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append("cw.visitOuterClass(");

-        appendConstant(owner);

-        buf.append(", ");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(desc);

-        buf.append(");\n\n");

-        text.add(buf.toString());

-    }

-

-    public void visitInnerClass(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        buf.setLength(0);

-        buf.append("cw.visitInnerClass(");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(outerName);

-        buf.append(", ");

-        appendConstant(innerName);

-        buf.append(", ");

-        appendAccess(access | ACCESS_INNER);

-        buf.append(");\n\n");

-        text.add(buf.toString());

-    }

-

-    public FieldVisitor visitField(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        buf.setLength(0);

-        buf.append("{\n");

-        buf.append("fv = cw.visitField(");

-        appendAccess(access | ACCESS_FIELD);

-        buf.append(", ");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(desc);

-        buf.append(", ");

-        appendConstant(signature);

-        buf.append(", ");

-        appendConstant(value);

-        buf.append(");\n");

-        text.add(buf.toString());

-        ASMifierFieldVisitor aav = new ASMifierFieldVisitor();

-        text.add(aav.getText());

-        text.add("}\n");

-        return aav;

-    }

-

-    public MethodVisitor visitMethod(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        buf.setLength(0);

-        buf.append("{\n");

-        buf.append("mv = cw.visitMethod(");

-        appendAccess(access);

-        buf.append(", ");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(desc);

-        buf.append(", ");

-        appendConstant(signature);

-        buf.append(", ");

-        if (exceptions != null && exceptions.length > 0) {

-            buf.append("new String[] {");

-            for (int i = 0; i < exceptions.length; ++i) {

-                buf.append(i == 0 ? " " : ", ");

-                appendConstant(exceptions[i]);

-            }

-            buf.append(" }");

-        } else {

-            buf.append("null");

-        }

-        buf.append(");\n");

-        text.add(buf.toString());

-        ASMifierMethodVisitor acv = createASMifierMethodVisitor();

-        text.add(acv.getText());

-        text.add("}\n");

-        return acv;

-    }

-

-    protected ASMifierMethodVisitor createASMifierMethodVisitor() {

-        return new ASMifierMethodVisitor();

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        buf.setLength(0);

-        buf.append("{\n");

-        buf.append("av0 = cw.visitAnnotation(");

-        appendConstant(desc);

-        buf.append(", ");

-        buf.append(visible);

-        buf.append(");\n");

-        text.add(buf.toString());

-        ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);

-        text.add(av.getText());

-        text.add("}\n");

-        return av;

-    }

-

-    public void visitEnd() {

-        text.add("cw.visitEnd();\n\n");

-        text.add("return cw.toByteArray();\n");

-        text.add("}\n");

-        text.add("}\n");

-        printList(pw, text);

-        pw.flush();

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Appends a string representation of the given access modifiers to {@link

-     * #buf buf}.

-     * 

-     * @param access some access modifiers.

-     */

-    void appendAccess(final int access) {

-        boolean first = true;

-        if ((access & Opcodes.ACC_PUBLIC) != 0) {

-            buf.append("ACC_PUBLIC");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_PRIVATE) != 0) {

-            buf.append("ACC_PRIVATE");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_PROTECTED) != 0) {

-            buf.append("ACC_PROTECTED");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_FINAL) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_FINAL");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_STATIC) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_STATIC");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            if ((access & ACCESS_CLASS) == 0) {

-                buf.append("ACC_SYNCHRONIZED");

-            } else {

-                buf.append("ACC_SUPER");

-            }

-            first = false;

-        }

-        if ((access & Opcodes.ACC_VOLATILE) != 0

-                && (access & ACCESS_FIELD) != 0)

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_VOLATILE");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0

-                && (access & ACCESS_FIELD) == 0)

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_BRIDGE");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0

-                && (access & ACCESS_FIELD) == 0)

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_VARARGS");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_TRANSIENT) != 0

-                && (access & ACCESS_FIELD) != 0)

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_TRANSIENT");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0

-                && (access & ACCESS_FIELD) == 0)

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_NATIVE");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_ENUM) != 0

-                && ((access & ACCESS_CLASS) != 0

-                        || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0))

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_ENUM");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_ANNOTATION) != 0

-                && (access & ACCESS_CLASS) != 0)

-        {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_ANNOTATION");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_ABSTRACT) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_ABSTRACT");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_INTERFACE) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_INTERFACE");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_STRICT) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_STRICT");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_SYNTHETIC");

-            first = false;

-        }

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            if (!first) {

-                buf.append(" + ");

-            }

-            buf.append("ACC_DEPRECATED");

-            first = false;

-        }

-        if (first) {

-            buf.append('0');

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/ASMifierFieldVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/ASMifierFieldVisitor.java
deleted file mode 100644
index 213d711..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/ASMifierFieldVisitor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.FieldVisitor;

-

-/**

- * A {@link FieldVisitor} that prints the ASM code that generates the fields it

- * visits.

- * 

- * @author Eric Bruneton

- */

-public class ASMifierFieldVisitor extends ASMifierAbstractVisitor implements

-        FieldVisitor

-{

-

-    /**

-     * Constructs a new {@link ASMifierFieldVisitor}.

-     */

-    public ASMifierFieldVisitor() {

-        super("fv");

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/ASMifierMethodVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/ASMifierMethodVisitor.java
deleted file mode 100644
index 58d9107..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/ASMifierMethodVisitor.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-

-import java.util.HashMap;

-

-/**

- * A {@link MethodVisitor} that prints the ASM code that generates the methods

- * it visits.

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements

-        MethodVisitor

-{

-

-    /**

-     * Constructs a new {@link ASMifierMethodVisitor} object.

-     */

-    public ASMifierMethodVisitor() {

-        super("mv");

-        this.labelNames = new HashMap();

-    }

-

-    public AnnotationVisitor visitAnnotationDefault() {

-        buf.setLength(0);

-        buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n");

-        text.add(buf.toString());

-        ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);

-        text.add(av.getText());

-        text.add("}\n");

-        return av;

-    }

-

-    public AnnotationVisitor visitParameterAnnotation(

-        final int parameter,

-        final String desc,

-        final boolean visible)

-    {

-        buf.setLength(0);

-        buf.append("{\n")

-                .append("av0 = mv.visitParameterAnnotation(")

-                .append(parameter)

-                .append(", ");

-        appendConstant(desc);

-        buf.append(", ").append(visible).append(");\n");

-        text.add(buf.toString());

-        ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);

-        text.add(av.getText());

-        text.add("}\n");

-        return av;

-    }

-

-    public void visitCode() {

-        text.add("mv.visitCode();\n");

-    }

-

-    public void visitFrame(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        buf.setLength(0);

-        switch (type) {

-            case Opcodes.F_NEW:

-            case Opcodes.F_FULL:

-                declareFrameTypes(nLocal, local);

-                declareFrameTypes(nStack, stack);

-                if (type == Opcodes.F_NEW) {

-                    buf.append("mv.visitFrame(Opcodes.F_NEW, ");

-                } else {

-                    buf.append("mv.visitFrame(Opcodes.F_FULL, ");

-                }

-                buf.append(nLocal).append(", new Object[] {");

-                appendFrameTypes(nLocal, local);

-                buf.append("}, ").append(nStack).append(", new Object[] {");

-                appendFrameTypes(nStack, stack);

-                buf.append('}');

-                break;

-            case Opcodes.F_APPEND:

-                declareFrameTypes(nLocal, local);

-                buf.append("mv.visitFrame(Opcodes.F_APPEND,")

-                        .append(nLocal)

-                        .append(", new Object[] {");

-                appendFrameTypes(nLocal, local);

-                buf.append("}, 0, null");

-                break;

-            case Opcodes.F_CHOP:

-                buf.append("mv.visitFrame(Opcodes.F_CHOP,")

-                        .append(nLocal)

-                        .append(", null, 0, null");

-                break;

-            case Opcodes.F_SAME:

-                buf.append("mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null");

-                break;

-            case Opcodes.F_SAME1:

-                declareFrameTypes(1, stack);

-                buf.append("mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");

-                appendFrameTypes(1, stack);

-                buf.append('}');

-                break;

-        }

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitInsn(final int opcode) {

-        buf.setLength(0);

-        buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitIntInsn(final int opcode, final int operand) {

-        buf.setLength(0);

-        buf.append("mv.visitIntInsn(")

-                .append(OPCODES[opcode])

-                .append(", ")

-                .append(opcode == Opcodes.NEWARRAY

-                        ? TYPES[operand]

-                        : Integer.toString(operand))

-                .append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitVarInsn(final int opcode, final int var) {

-        buf.setLength(0);

-        buf.append("mv.visitVarInsn(")

-                .append(OPCODES[opcode])

-                .append(", ")

-                .append(var)

-                .append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitTypeInsn(final int opcode, final String type) {

-        buf.setLength(0);

-        buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", ");

-        appendConstant(type);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitFieldInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", ");

-        appendConstant(owner);

-        buf.append(", ");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(desc);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitMethodInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", ");

-        appendConstant(owner);

-        buf.append(", ");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(desc);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitJumpInsn(final int opcode, final Label label) {

-        buf.setLength(0);

-        declareLabel(label);

-        buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", ");

-        appendLabel(label);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitLabel(final Label label) {

-        buf.setLength(0);

-        declareLabel(label);

-        buf.append("mv.visitLabel(");

-        appendLabel(label);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitLdcInsn(final Object cst) {

-        buf.setLength(0);

-        buf.append("mv.visitLdcInsn(");

-        appendConstant(cst);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitIincInsn(final int var, final int increment) {

-        buf.setLength(0);

-        buf.append("mv.visitIincInsn(")

-                .append(var)

-                .append(", ")

-                .append(increment)

-                .append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitTableSwitchInsn(

-        final int min,

-        final int max,

-        final Label dflt,

-        final Label[] labels)

-    {

-        buf.setLength(0);

-        for (int i = 0; i < labels.length; ++i) {

-            declareLabel(labels[i]);

-        }

-        declareLabel(dflt);

-

-        buf.append("mv.visitTableSwitchInsn(")

-                .append(min)

-                .append(", ")

-                .append(max)

-                .append(", ");

-        appendLabel(dflt);

-        buf.append(", new Label[] {");

-        for (int i = 0; i < labels.length; ++i) {

-            buf.append(i == 0 ? " " : ", ");

-            appendLabel(labels[i]);

-        }

-        buf.append(" });\n");

-        text.add(buf.toString());

-    }

-

-    public void visitLookupSwitchInsn(

-        final Label dflt,

-        final int[] keys,

-        final Label[] labels)

-    {

-        buf.setLength(0);

-        for (int i = 0; i < labels.length; ++i) {

-            declareLabel(labels[i]);

-        }

-        declareLabel(dflt);

-

-        buf.append("mv.visitLookupSwitchInsn(");

-        appendLabel(dflt);

-        buf.append(", new int[] {");

-        for (int i = 0; i < keys.length; ++i) {

-            buf.append(i == 0 ? " " : ", ").append(keys[i]);

-        }

-        buf.append(" }, new Label[] {");

-        for (int i = 0; i < labels.length; ++i) {

-            buf.append(i == 0 ? " " : ", ");

-            appendLabel(labels[i]);

-        }

-        buf.append(" });\n");

-        text.add(buf.toString());

-    }

-

-    public void visitMultiANewArrayInsn(final String desc, final int dims) {

-        buf.setLength(0);

-        buf.append("mv.visitMultiANewArrayInsn(");

-        appendConstant(desc);

-        buf.append(", ").append(dims).append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitTryCatchBlock(

-        final Label start,

-        final Label end,

-        final Label handler,

-        final String type)

-    {

-        buf.setLength(0);

-        declareLabel(start);

-        declareLabel(end);

-        declareLabel(handler);

-        buf.append("mv.visitTryCatchBlock(");

-        appendLabel(start);

-        buf.append(", ");

-        appendLabel(end);

-        buf.append(", ");

-        appendLabel(handler);

-        buf.append(", ");

-        appendConstant(type);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitLocalVariable(

-        final String name,

-        final String desc,

-        final String signature,

-        final Label start,

-        final Label end,

-        final int index)

-    {

-        buf.setLength(0);

-        buf.append("mv.visitLocalVariable(");

-        appendConstant(name);

-        buf.append(", ");

-        appendConstant(desc);

-        buf.append(", ");

-        appendConstant(signature);

-        buf.append(", ");

-        appendLabel(start);

-        buf.append(", ");

-        appendLabel(end);

-        buf.append(", ").append(index).append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitLineNumber(final int line, final Label start) {

-        buf.setLength(0);

-        buf.append("mv.visitLineNumber(").append(line).append(", ");

-        appendLabel(start);

-        buf.append(");\n");

-        text.add(buf.toString());

-    }

-

-    public void visitMaxs(final int maxStack, final int maxLocals) {

-        buf.setLength(0);

-        buf.append("mv.visitMaxs(")

-                .append(maxStack)

-                .append(", ")

-                .append(maxLocals)

-                .append(");\n");

-        text.add(buf.toString());

-    }

-

-    private void declareFrameTypes(final int n, final Object[] o) {

-        for (int i = 0; i < n; ++i) {

-            if (o[i] instanceof Label) {

-                declareLabel((Label) o[i]);

-            }

-        }

-    }

-

-    private void appendFrameTypes(final int n, final Object[] o) {

-        for (int i = 0; i < n; ++i) {

-            if (i > 0) {

-                buf.append(", ");

-            }

-            if (o[i] instanceof String) {

-                appendConstant(o[i]);

-            } else if (o[i] instanceof Integer) {

-                switch (((Integer) o[i]).intValue()) {

-                    case 0:

-                        buf.append("Opcodes.TOP");

-                        break;

-                    case 1:

-                        buf.append("Opcodes.INTEGER");

-                        break;

-                    case 2:

-                        buf.append("Opcodes.FLOAT");

-                        break;

-                    case 3:

-                        buf.append("Opcodes.DOUBLE");

-                        break;

-                    case 4:

-                        buf.append("Opcodes.LONG");

-                        break;

-                    case 5:

-                        buf.append("Opcodes.NULL");

-                        break;

-                    case 6:

-                        buf.append("Opcodes.UNINITIALIZED_THIS");

-                        break;

-                }

-            } else {

-                appendLabel((Label) o[i]);

-            }

-        }

-    }

-

-    /**

-     * Appends a declaration of the given label to {@link #buf buf}. This

-     * declaration is of the form "Label lXXX = new Label();". Does nothing if

-     * the given label has already been declared.

-     * 

-     * @param l a label.

-     */

-    private void declareLabel(final Label l) {

-        String name = (String) labelNames.get(l);

-        if (name == null) {

-            name = "l" + labelNames.size();

-            labelNames.put(l, name);

-            buf.append("Label ").append(name).append(" = new Label();\n");

-        }

-    }

-

-    /**

-     * Appends the name of the given label to {@link #buf buf}. The given label

-     * <i>must</i> already have a name. One way to ensure this is to always

-     * call {@link #declareLabel declared} before calling this method.

-     * 

-     * @param l a label.

-     */

-    private void appendLabel(final Label l) {

-        buf.append((String) labelNames.get(l));

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/AbstractVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/AbstractVisitor.java
deleted file mode 100644
index c369151..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/AbstractVisitor.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import java.io.PrintWriter;

-import java.util.ArrayList;

-import java.util.List;

-

-import org.mockito.asm.Attribute;

-

-/**

- * An abstract visitor.

- * 

- * @author Eric Bruneton

- */

-public abstract class AbstractVisitor {

-

-    /**

-     * The names of the Java Virtual Machine opcodes.

-     */

-    public static final String[] OPCODES;

-    /**

-     * Types for <code>operand</code> parameter of the

-     * {@link org.mockito.asm.MethodVisitor#visitIntInsn} method when

-     * <code>opcode</code> is <code>NEWARRAY</code>.

-     */

-    public static final String[] TYPES;

-

-    static {

-        String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2,"

-                + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0,"

-                + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"

-                + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD,"

-                + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE,"

-                + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"

-                + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP,"

-                + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD,"

-                + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"

-                + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL,"

-                + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L,"

-                + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"

-                + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE,"

-                + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE,"

-                + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"

-                + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC,"

-                + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL,"

-                + "INVOKESTATIC,INVOKEINTERFACE,,NEW,NEWARRAY,ANEWARRAY,"

-                + "ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,MONITORENTER,"

-                + "MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";

-        OPCODES = new String[200];

-        int i = 0;

-        int j = 0;

-        int l;

-        while ((l = s.indexOf(',', j)) > 0) {

-            OPCODES[i++] = j + 1 == l ? null : s.substring(j, l);

-            j = l + 1;

-        }

-

-        s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";

-        TYPES = new String[12];

-        j = 0;

-        i = 4;

-        while ((l = s.indexOf(',', j)) > 0) {

-            TYPES[i++] = s.substring(j, l);

-            j = l + 1;

-        }

-    }

-

-    /**

-     * The text to be printed. Since the code of methods is not necessarily

-     * visited in sequential order, one method after the other, but can be

-     * interlaced (some instructions from method one, then some instructions

-     * from method two, then some instructions from method one again...), it is

-     * not possible to print the visited instructions directly to a sequential

-     * stream. A class is therefore printed in a two steps process: a string

-     * tree is constructed during the visit, and printed to a sequential stream

-     * at the end of the visit. This string tree is stored in this field, as a

-     * string list that can contain other string lists, which can themselves

-     * contain other string lists, and so on.

-     */

-    public final List text;

-

-    /**

-     * A buffer that can be used to create strings.

-     */

-    protected final StringBuffer buf;

-

-    /**

-     * Constructs a new {@link AbstractVisitor}.

-     */

-    protected AbstractVisitor() {

-        this.text = new ArrayList();

-        this.buf = new StringBuffer();

-    }

-

-    /**

-     * Returns the text constructed by this visitor.

-     * 

-     * @return the text constructed by this visitor.

-     */

-    public List getText() {

-        return text;

-    }

-

-    /**

-     * Prints the text constructed by this visitor.

-     * 

-     * @param pw the print writer to be used.

-     */

-    public void print(final PrintWriter pw) {

-        printList(pw, text);

-    }

-    

-    /**

-     * Appends a quoted string to a given buffer.

-     * 

-     * @param buf the buffer where the string must be added.

-     * @param s the string to be added.

-     */

-    public static void appendString(final StringBuffer buf, final String s) {

-        buf.append('\"');

-        for (int i = 0; i < s.length(); ++i) {

-            char c = s.charAt(i);

-            if (c == '\n') {

-                buf.append("\\n");

-            } else if (c == '\r') {

-                buf.append("\\r");

-            } else if (c == '\\') {

-                buf.append("\\\\");

-            } else if (c == '"') {

-                buf.append("\\\"");

-            } else if (c < 0x20 || c > 0x7f) {

-                buf.append("\\u");

-                if (c < 0x10) {

-                    buf.append("000");

-                } else if (c < 0x100) {

-                    buf.append("00");

-                } else if (c < 0x1000) {

-                    buf.append('0');

-                }

-                buf.append(Integer.toString(c, 16));

-            } else {

-                buf.append(c);

-            }

-        }

-        buf.append('\"');

-    }

-

-    /**

-     * Prints the given string tree.

-     * 

-     * @param pw the writer to be used to print the tree.

-     * @param l a string tree, i.e., a string list that can contain other string

-     *        lists, and so on recursively.

-     */

-    static void printList(final PrintWriter pw, final List l) {

-        for (int i = 0; i < l.size(); ++i) {

-            Object o = l.get(i);

-            if (o instanceof List) {

-                printList(pw, (List) o);

-            } else {

-                pw.print(o.toString());

-            }

-        }

-    }

-

-    /**

-     * Returns the default {@link ASMifiable} prototypes.

-     * 

-     * @return the default {@link ASMifiable} prototypes.

-     */

-    public static Attribute[] getDefaultAttributes() {

-        return new Attribute[0];

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/CheckAnnotationAdapter.java b/cglib-and-asm/src/org/mockito/asm/util/CheckAnnotationAdapter.java
deleted file mode 100644
index 8afa075..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/CheckAnnotationAdapter.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Type;

-

-/**

- * An {@link AnnotationVisitor} that checks that its methods are properly used.

- * 

- * @author Eric Bruneton

- */

-public class CheckAnnotationAdapter implements AnnotationVisitor {

-

-    private final AnnotationVisitor av;

-

-    private final boolean named;

-

-    private boolean end;

-

-    public CheckAnnotationAdapter(final AnnotationVisitor av) {

-        this(av, true);

-    }

-

-    CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {

-        this.av = av;

-        this.named = named;

-    }

-

-    public void visit(final String name, final Object value) {

-        checkEnd();

-        checkName(name);

-        if (!(value instanceof Byte || value instanceof Boolean

-                || value instanceof Character || value instanceof Short

-                || value instanceof Integer || value instanceof Long

-                || value instanceof Float || value instanceof Double

-                || value instanceof String || value instanceof Type

-                || value instanceof byte[] || value instanceof boolean[]

-                || value instanceof char[] || value instanceof short[]

-                || value instanceof int[] || value instanceof long[]

-                || value instanceof float[] || value instanceof double[]))

-        {

-            throw new IllegalArgumentException("Invalid annotation value");

-        }

-        if (av != null) {

-            av.visit(name, value);

-        }

-    }

-

-    public void visitEnum(

-        final String name,

-        final String desc,

-        final String value)

-    {

-        checkEnd();

-        checkName(name);

-        CheckMethodAdapter.checkDesc(desc, false);

-        if (value == null) {

-            throw new IllegalArgumentException("Invalid enum value");

-        }

-        if (av != null) {

-            av.visitEnum(name, desc, value);

-        }

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String name,

-        final String desc)

-    {

-        checkEnd();

-        checkName(name);

-        CheckMethodAdapter.checkDesc(desc, false);

-        return new CheckAnnotationAdapter(av == null

-                ? null

-                : av.visitAnnotation(name, desc));

-    }

-

-    public AnnotationVisitor visitArray(final String name) {

-        checkEnd();

-        checkName(name);

-        return new CheckAnnotationAdapter(av == null

-                ? null

-                : av.visitArray(name), false);

-    }

-

-    public void visitEnd() {

-        checkEnd();

-        end = true;

-        if (av != null) {

-            av.visitEnd();

-        }

-    }

-

-    private void checkEnd() {

-        if (end) {

-            throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");

-        }

-    }

-

-    private void checkName(final String name) {

-        if (named && name == null) {

-            throw new IllegalArgumentException("Annotation value name must not be null");

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/CheckClassAdapter.java b/cglib-and-asm/src/org/mockito/asm/util/CheckClassAdapter.java
deleted file mode 100644
index d828efd..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/CheckClassAdapter.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import java.io.FileInputStream;

-import java.io.PrintWriter;

-import java.util.List;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.ClassAdapter;

-import org.mockito.asm.ClassReader;

-import org.mockito.asm.ClassVisitor;

-import org.mockito.asm.FieldVisitor;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-import org.mockito.asm.tree.ClassNode;

-import org.mockito.asm.tree.MethodNode;

-import org.mockito.asm.tree.TryCatchBlockNode;

-import org.mockito.asm.tree.analysis.Analyzer;

-import org.mockito.asm.tree.analysis.Frame;

-import org.mockito.asm.tree.analysis.SimpleVerifier;

-

-/**

- * A {@link ClassAdapter} that checks that its methods are properly used. More

- * precisely this class adapter checks each method call individually, based

- * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>

- * of method calls. For example, the invalid sequence

- * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,

- * "i", "D", null)</tt>

- * will <i>not</i> be detected by this class adapter.

- * 

- * <p><code>CheckClassAdapter</code> can be also used to verify bytecode

- * transformations in order to make sure transformed bytecode is sane. For

- * example:

- * 

- * <pre>

- *   InputStream is = ...; // get bytes for the source class

- *   ClassReader cr = new ClassReader(is);

- *   ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);

- *   ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));

- *   cr.accept(cv, 0);

- * 

- *   StringWriter sw = new StringWriter();

- *   PrintWriter pw = new PrintWriter(sw);

- *   CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);

- *   assertTrue(sw.toString(), sw.toString().length()==0);

- * </pre>

- * 

- * Above code runs transformed bytecode trough the

- * <code>CheckClassAdapter</code>. It won't be exactly the same verification

- * as JVM does, but it run data flow analysis for the code of each method and

- * checks that expectations are met for each method instruction.

- * 

- * <p>If method bytecode has errors, assertion text will show the erroneous

- * instruction number and dump of the failed method with information about

- * locals and stack slot for each instruction. For example (format is -

- * insnNumber locals : stack):

- * 

- * <pre>

- * org.mockito.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .

- *   at org.mockito.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)

- *   at org.mockito.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)

- * ...

- * remove()V

- * 00000 LinkedBlockingQueue$Itr . . . . . . . .  :

- *   ICONST_0

- * 00001 LinkedBlockingQueue$Itr . . . . . . . .  : I

- *   ISTORE 2

- * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :

- * ...

- * 

- * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  : 

- *   ILOAD 1

- * 00072 <b>?</b>                

- *   INVOKESPECIAL java/lang/Integer.<init> (I)V

- * ...

- * </pre>

- * 

- * In the above output you can see that variable 1 loaded by

- * <code>ILOAD 1</code> instruction at position <code>00071</code> is not

- * initialized. You can also see that at the beginning of the method (code

- * inserted by the transformation) variable 2 is initialized.

- * 

- * <p>Note that when used like that, <code>CheckClassAdapter.verify()</code>

- * can trigger additional class loading, because it is using

- * <code>SimpleVerifier</code>.

- * 

- * @author Eric Bruneton

- */

-public class CheckClassAdapter extends ClassAdapter {

-

-    /**

-     * <tt>true</tt> if the visit method has been called.

-     */

-    private boolean start;

-

-    /**

-     * <tt>true</tt> if the visitSource method has been called.

-     */

-    private boolean source;

-

-    /**

-     * <tt>true</tt> if the visitOuterClass method has been called.

-     */

-    private boolean outer;

-

-    /**

-     * <tt>true</tt> if the visitEnd method has been called.

-     */

-    private boolean end;

-

-    /**

-     * Checks a given class. <p> Usage: CheckClassAdapter &lt;fully qualified

-     * class name or class file name&gt;

-     * 

-     * @param args the command line arguments.

-     * 

-     * @throws Exception if the class cannot be found, or if an IO exception

-     *         occurs.

-     */

-    public static void main(final String[] args) throws Exception {

-        if (args.length != 1) {

-            System.err.println("Verifies the given class.");

-            System.err.println("Usage: CheckClassAdapter "

-                    + "<fully qualified class name or class file name>");

-            return;

-        }

-        ClassReader cr;

-        if (args[0].endsWith(".class")) {

-            cr = new ClassReader(new FileInputStream(args[0]));

-        } else {

-            cr = new ClassReader(args[0]);

-        }

-

-        verify(cr, false, new PrintWriter(System.err));

-    }

-

-    /**

-     * Checks a given class

-     * 

-     * @param cr a <code>ClassReader</code> that contains bytecode for the

-     *        analysis.

-     * @param dump true if bytecode should be printed out not only when errors

-     *        are found.

-     * @param pw write where results going to be printed

-     */

-    public static void verify(

-        final ClassReader cr,

-        final boolean dump,

-        final PrintWriter pw)

-    {

-        ClassNode cn = new ClassNode();

-        cr.accept(new CheckClassAdapter(cn), ClassReader.SKIP_DEBUG);

-

-        Type syperType = cn.superName == null

-                ? null

-                : Type.getObjectType(cn.superName);

-        List methods = cn.methods;

-        for (int i = 0; i < methods.size(); ++i) {

-            MethodNode method = (MethodNode) methods.get(i);

-            Analyzer a = new Analyzer(new SimpleVerifier(Type.getObjectType(cn.name),

-                    syperType,

-                    false));

-            try {

-                a.analyze(cn.name, method);

-                if (!dump) {

-                    continue;

-                }

-            } catch (Exception e) {

-                e.printStackTrace(pw);

-            }

-            Frame[] frames = a.getFrames();

-

-            TraceMethodVisitor mv = new TraceMethodVisitor();

-

-            pw.println(method.name + method.desc);

-            for (int j = 0; j < method.instructions.size(); ++j) {

-                method.instructions.get(j).accept(mv);

-

-                StringBuffer s = new StringBuffer();

-                Frame f = frames[j];

-                if (f == null) {

-                    s.append('?');

-                } else {

-                    for (int k = 0; k < f.getLocals(); ++k) {

-                        s.append(getShortName(f.getLocal(k).toString()))

-                                .append(' ');

-                    }

-                    s.append(" : ");

-                    for (int k = 0; k < f.getStackSize(); ++k) {

-                        s.append(getShortName(f.getStack(k).toString()))

-                                .append(' ');

-                    }

-                }

-                while (s.length() < method.maxStack + method.maxLocals + 1) {

-                    s.append(' ');

-                }

-                pw.print(Integer.toString(j + 100000).substring(1));

-                pw.print(" " + s + " : " + mv.buf); // mv.text.get(j));

-            }

-            for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {

-                ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv);

-                pw.print(" " + mv.buf);

-            }

-            pw.println();

-        }

-        pw.flush();

-    }

-

-    private static String getShortName(final String name) {

-        int n = name.lastIndexOf('/');

-        int k = name.length();

-        if (name.charAt(k - 1) == ';') {

-            k--;

-        }

-        return n == -1 ? name : name.substring(n + 1, k);

-    }

-

-    /**

-     * Constructs a new {@link CheckClassAdapter}.

-     * 

-     * @param cv the class visitor to which this adapter must delegate calls.

-     */

-    public CheckClassAdapter(final ClassVisitor cv) {

-        super(cv);

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the ClassVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(

-        final int version,

-        final int access,

-        final String name,

-        final String signature,

-        final String superName,

-        final String[] interfaces)

-    {

-        if (start) {

-            throw new IllegalStateException("visit must be called only once");

-        }

-        start = true;

-        checkState();

-        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL

-                + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE

-                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC

-                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM

-                + Opcodes.ACC_DEPRECATED);

-        if (name == null || !name.endsWith("package-info")) {

-            CheckMethodAdapter.checkInternalName(name, "class name");

-        }

-        if ("java/lang/Object".equals(name)) {

-            if (superName != null) {

-                throw new IllegalArgumentException("The super class name of the Object class must be 'null'");

-            }

-        } else {

-            CheckMethodAdapter.checkInternalName(superName, "super class name");

-        }

-        if (signature != null) {

-            CheckMethodAdapter.checkClassSignature(signature);

-        }

-        if ((access & Opcodes.ACC_INTERFACE) != 0) {

-            if (!"java/lang/Object".equals(superName)) {

-                throw new IllegalArgumentException("The super class name of interfaces must be 'java/lang/Object'");

-            }

-        }

-        if (interfaces != null) {

-            for (int i = 0; i < interfaces.length; ++i) {

-                CheckMethodAdapter.checkInternalName(interfaces[i],

-                        "interface name at index " + i);

-            }

-        }

-        cv.visit(version, access, name, signature, superName, interfaces);

-    }

-

-    public void visitSource(final String file, final String debug) {

-        checkState();

-        if (source) {

-            throw new IllegalStateException("visitSource can be called only once.");

-        }

-        source = true;

-        cv.visitSource(file, debug);

-    }

-

-    public void visitOuterClass(

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        checkState();

-        if (outer) {

-            throw new IllegalStateException("visitOuterClass can be called only once.");

-        }

-        outer = true;

-        if (owner == null) {

-            throw new IllegalArgumentException("Illegal outer class owner");

-        }

-        if (desc != null) {

-            CheckMethodAdapter.checkMethodDesc(desc);

-        }

-        cv.visitOuterClass(owner, name, desc);

-    }

-

-    public void visitInnerClass(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        checkState();

-        CheckMethodAdapter.checkInternalName(name, "class name");

-        if (outerName != null) {

-            CheckMethodAdapter.checkInternalName(outerName, "outer class name");

-        }

-        if (innerName != null) {

-            CheckMethodAdapter.checkIdentifier(innerName, "inner class name");

-        }

-        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE

-                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC

-                + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE

-                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC

-                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);

-        cv.visitInnerClass(name, outerName, innerName, access);

-    }

-

-    public FieldVisitor visitField(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        checkState();

-        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE

-                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC

-                + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE

-                + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC

-                + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED);

-        CheckMethodAdapter.checkIdentifier(name, "field name");

-        CheckMethodAdapter.checkDesc(desc, false);

-        if (signature != null) {

-            CheckMethodAdapter.checkFieldSignature(signature);

-        }

-        if (value != null) {

-            CheckMethodAdapter.checkConstant(value);

-        }

-        FieldVisitor av = cv.visitField(access, name, desc, signature, value);

-        return new CheckFieldAdapter(av);

-    }

-

-    public MethodVisitor visitMethod(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        checkState();

-        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE

-                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC

-                + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED

-                + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE

-                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT

-                + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED);

-        CheckMethodAdapter.checkMethodIdentifier(name, "method name");

-        CheckMethodAdapter.checkMethodDesc(desc);

-        if (signature != null) {

-            CheckMethodAdapter.checkMethodSignature(signature);

-        }

-        if (exceptions != null) {

-            for (int i = 0; i < exceptions.length; ++i) {

-                CheckMethodAdapter.checkInternalName(exceptions[i],

-                        "exception name at index " + i);

-            }

-        }

-        return new CheckMethodAdapter(cv.visitMethod(access,

-                name,

-                desc,

-                signature,

-                exceptions));

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        checkState();

-        CheckMethodAdapter.checkDesc(desc, false);

-        return new CheckAnnotationAdapter(cv.visitAnnotation(desc, visible));

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        checkState();

-        if (attr == null) {

-            throw new IllegalArgumentException("Invalid attribute (must not be null)");

-        }

-        cv.visitAttribute(attr);

-    }

-

-    public void visitEnd() {

-        checkState();

-        end = true;

-        cv.visitEnd();

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    /**

-     * Checks that the visit method has been called and that visitEnd has not

-     * been called.

-     */

-    private void checkState() {

-        if (!start) {

-            throw new IllegalStateException("Cannot visit member before visit has been called.");

-        }

-        if (end) {

-            throw new IllegalStateException("Cannot visit member after visitEnd has been called.");

-        }

-    }

-

-    /**

-     * Checks that the given access flags do not contain invalid flags. This

-     * method also checks that mutually incompatible flags are not set

-     * simultaneously.

-     * 

-     * @param access the access flags to be checked

-     * @param possibleAccess the valid access flags.

-     */

-    static void checkAccess(final int access, final int possibleAccess) {

-        if ((access & ~possibleAccess) != 0) {

-            throw new IllegalArgumentException("Invalid access flags: "

-                    + access);

-        }

-        int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;

-        int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;

-        int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;

-        if (pub + pri + pro > 1) {

-            throw new IllegalArgumentException("public private and protected are mutually exclusive: "

-                    + access);

-        }

-        int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;

-        int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;

-        if (fin + abs > 1) {

-            throw new IllegalArgumentException("final and abstract are mutually exclusive: "

-                    + access);

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/CheckFieldAdapter.java b/cglib-and-asm/src/org/mockito/asm/util/CheckFieldAdapter.java
deleted file mode 100644
index 82cc37d..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/CheckFieldAdapter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.FieldVisitor;

-

-/**

- * A {@link FieldVisitor} that checks that its methods are properly used.

- */

-public class CheckFieldAdapter implements FieldVisitor {

-

-    private final FieldVisitor fv;

-

-    private boolean end;

-

-    public CheckFieldAdapter(final FieldVisitor fv) {

-        this.fv = fv;

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        checkEnd();

-        CheckMethodAdapter.checkDesc(desc, false);

-        return new CheckAnnotationAdapter(fv.visitAnnotation(desc, visible));

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        checkEnd();

-        if (attr == null) {

-            throw new IllegalArgumentException("Invalid attribute (must not be null)");

-        }

-        fv.visitAttribute(attr);

-    }

-

-    public void visitEnd() {

-        checkEnd();

-        end = true;

-        fv.visitEnd();

-    }

-

-    private void checkEnd() {

-        if (end) {

-            throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/CheckMethodAdapter.java b/cglib-and-asm/src/org/mockito/asm/util/CheckMethodAdapter.java
deleted file mode 100644
index f255892..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/CheckMethodAdapter.java
+++ /dev/null
@@ -1,1328 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodAdapter;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-

-import java.util.HashMap;

-import java.util.Map;

-

-/**

- * A {@link MethodAdapter} that checks that its methods are properly used. More

- * precisely this code adapter checks each instruction individually (i.e., each

- * visit method checks some preconditions based <i>only</i> on its arguments -

- * such as the fact that the given opcode is correct for a given visit method),

- * but does <i>not</i> check the <i>sequence</i> of instructions. For example,

- * in a method whose signature is <tt>void m ()</tt>, the invalid instruction

- * IRETURN, or the invalid sequence IADD L2I will <i>not</i> be detected by

- * this code adapter.

- * 

- * @author Eric Bruneton

- */

-public class CheckMethodAdapter extends MethodAdapter {

-

-    /**

-     * <tt>true</tt> if the visitCode method has been called.

-     */

-    private boolean startCode;

-

-    /**

-     * <tt>true</tt> if the visitMaxs method has been called.

-     */

-    private boolean endCode;

-

-    /**

-     * <tt>true</tt> if the visitEnd method has been called.

-     */

-    private boolean endMethod;

-

-    /**

-     * The already visited labels. This map associate Integer values to Label

-     * keys.

-     */

-    private final Map labels;

-

-    /**

-     * Code of the visit method to be used for each opcode.

-     */

-    private static final int[] TYPE;

-

-    static {

-        String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"

-                + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"

-                + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"

-                + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";

-        TYPE = new int[s.length()];

-        for (int i = 0; i < TYPE.length; ++i) {

-            TYPE[i] = s.charAt(i) - 'A' - 1;

-        }

-    }

-

-    // code to generate the above string

-    // public static void main (String[] args) {

-    // int[] TYPE = new int[] {

-    // 0, //NOP

-    // 0, //ACONST_NULL

-    // 0, //ICONST_M1

-    // 0, //ICONST_0

-    // 0, //ICONST_1

-    // 0, //ICONST_2

-    // 0, //ICONST_3

-    // 0, //ICONST_4

-    // 0, //ICONST_5

-    // 0, //LCONST_0

-    // 0, //LCONST_1

-    // 0, //FCONST_0

-    // 0, //FCONST_1

-    // 0, //FCONST_2

-    // 0, //DCONST_0

-    // 0, //DCONST_1

-    // 1, //BIPUSH

-    // 1, //SIPUSH

-    // 7, //LDC

-    // -1, //LDC_W

-    // -1, //LDC2_W

-    // 2, //ILOAD

-    // 2, //LLOAD

-    // 2, //FLOAD

-    // 2, //DLOAD

-    // 2, //ALOAD

-    // -1, //ILOAD_0

-    // -1, //ILOAD_1

-    // -1, //ILOAD_2

-    // -1, //ILOAD_3

-    // -1, //LLOAD_0

-    // -1, //LLOAD_1

-    // -1, //LLOAD_2

-    // -1, //LLOAD_3

-    // -1, //FLOAD_0

-    // -1, //FLOAD_1

-    // -1, //FLOAD_2

-    // -1, //FLOAD_3

-    // -1, //DLOAD_0

-    // -1, //DLOAD_1

-    // -1, //DLOAD_2

-    // -1, //DLOAD_3

-    // -1, //ALOAD_0

-    // -1, //ALOAD_1

-    // -1, //ALOAD_2

-    // -1, //ALOAD_3

-    // 0, //IALOAD

-    // 0, //LALOAD

-    // 0, //FALOAD

-    // 0, //DALOAD

-    // 0, //AALOAD

-    // 0, //BALOAD

-    // 0, //CALOAD

-    // 0, //SALOAD

-    // 2, //ISTORE

-    // 2, //LSTORE

-    // 2, //FSTORE

-    // 2, //DSTORE

-    // 2, //ASTORE

-    // -1, //ISTORE_0

-    // -1, //ISTORE_1

-    // -1, //ISTORE_2

-    // -1, //ISTORE_3

-    // -1, //LSTORE_0

-    // -1, //LSTORE_1

-    // -1, //LSTORE_2

-    // -1, //LSTORE_3

-    // -1, //FSTORE_0

-    // -1, //FSTORE_1

-    // -1, //FSTORE_2

-    // -1, //FSTORE_3

-    // -1, //DSTORE_0

-    // -1, //DSTORE_1

-    // -1, //DSTORE_2

-    // -1, //DSTORE_3

-    // -1, //ASTORE_0

-    // -1, //ASTORE_1

-    // -1, //ASTORE_2

-    // -1, //ASTORE_3

-    // 0, //IASTORE

-    // 0, //LASTORE

-    // 0, //FASTORE

-    // 0, //DASTORE

-    // 0, //AASTORE

-    // 0, //BASTORE

-    // 0, //CASTORE

-    // 0, //SASTORE

-    // 0, //POP

-    // 0, //POP2

-    // 0, //DUP

-    // 0, //DUP_X1

-    // 0, //DUP_X2

-    // 0, //DUP2

-    // 0, //DUP2_X1

-    // 0, //DUP2_X2

-    // 0, //SWAP

-    // 0, //IADD

-    // 0, //LADD

-    // 0, //FADD

-    // 0, //DADD

-    // 0, //ISUB

-    // 0, //LSUB

-    // 0, //FSUB

-    // 0, //DSUB

-    // 0, //IMUL

-    // 0, //LMUL

-    // 0, //FMUL

-    // 0, //DMUL

-    // 0, //IDIV

-    // 0, //LDIV

-    // 0, //FDIV

-    // 0, //DDIV

-    // 0, //IREM

-    // 0, //LREM

-    // 0, //FREM

-    // 0, //DREM

-    // 0, //INEG

-    // 0, //LNEG

-    // 0, //FNEG

-    // 0, //DNEG

-    // 0, //ISHL

-    // 0, //LSHL

-    // 0, //ISHR

-    // 0, //LSHR

-    // 0, //IUSHR

-    // 0, //LUSHR

-    // 0, //IAND

-    // 0, //LAND

-    // 0, //IOR

-    // 0, //LOR

-    // 0, //IXOR

-    // 0, //LXOR

-    // 8, //IINC

-    // 0, //I2L

-    // 0, //I2F

-    // 0, //I2D

-    // 0, //L2I

-    // 0, //L2F

-    // 0, //L2D

-    // 0, //F2I

-    // 0, //F2L

-    // 0, //F2D

-    // 0, //D2I

-    // 0, //D2L

-    // 0, //D2F

-    // 0, //I2B

-    // 0, //I2C

-    // 0, //I2S

-    // 0, //LCMP

-    // 0, //FCMPL

-    // 0, //FCMPG

-    // 0, //DCMPL

-    // 0, //DCMPG

-    // 6, //IFEQ

-    // 6, //IFNE

-    // 6, //IFLT

-    // 6, //IFGE

-    // 6, //IFGT

-    // 6, //IFLE

-    // 6, //IF_ICMPEQ

-    // 6, //IF_ICMPNE

-    // 6, //IF_ICMPLT

-    // 6, //IF_ICMPGE

-    // 6, //IF_ICMPGT

-    // 6, //IF_ICMPLE

-    // 6, //IF_ACMPEQ

-    // 6, //IF_ACMPNE

-    // 6, //GOTO

-    // 6, //JSR

-    // 2, //RET

-    // 9, //TABLESWITCH

-    // 10, //LOOKUPSWITCH

-    // 0, //IRETURN

-    // 0, //LRETURN

-    // 0, //FRETURN

-    // 0, //DRETURN

-    // 0, //ARETURN

-    // 0, //RETURN

-    // 4, //GETSTATIC

-    // 4, //PUTSTATIC

-    // 4, //GETFIELD

-    // 4, //PUTFIELD

-    // 5, //INVOKEVIRTUAL

-    // 5, //INVOKESPECIAL

-    // 5, //INVOKESTATIC

-    // 5, //INVOKEINTERFACE

-    // -1, //UNUSED

-    // 3, //NEW

-    // 1, //NEWARRAY

-    // 3, //ANEWARRAY

-    // 0, //ARRAYLENGTH

-    // 0, //ATHROW

-    // 3, //CHECKCAST

-    // 3, //INSTANCEOF

-    // 0, //MONITORENTER

-    // 0, //MONITOREXIT

-    // -1, //WIDE

-    // 11, //MULTIANEWARRAY

-    // 6, //IFNULL

-    // 6, //IFNONNULL

-    // -1, //GOTO_W

-    // -1 //JSR_W

-    // };

-    // for (int i = 0; i < TYPE.length; ++i) {

-    // System.out.print((char)(TYPE[i] + 1 + 'A'));

-    // }

-    // System.out.println();

-    // }

-

-    /**

-     * Constructs a new {@link CheckMethodAdapter} object.

-     * 

-     * @param cv the code visitor to which this adapter must delegate calls.

-     */

-    public CheckMethodAdapter(final MethodVisitor cv) {

-        super(cv);

-        this.labels = new HashMap();

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        checkEndMethod();

-        checkDesc(desc, false);

-        return new CheckAnnotationAdapter(mv.visitAnnotation(desc, visible));

-    }

-

-    public AnnotationVisitor visitAnnotationDefault() {

-        checkEndMethod();

-        return new CheckAnnotationAdapter(mv.visitAnnotationDefault(), false);

-    }

-

-    public AnnotationVisitor visitParameterAnnotation(

-        final int parameter,

-        final String desc,

-        final boolean visible)

-    {

-        checkEndMethod();

-        checkDesc(desc, false);

-        return new CheckAnnotationAdapter(mv.visitParameterAnnotation(parameter,

-                desc,

-                visible));

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        checkEndMethod();

-        if (attr == null) {

-            throw new IllegalArgumentException("Invalid attribute (must not be null)");

-        }

-        mv.visitAttribute(attr);

-    }

-

-    public void visitCode() {

-        startCode = true;

-        mv.visitCode();

-    }

-

-    public void visitFrame(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        int mLocal;

-        int mStack;

-        switch (type) {

-            case Opcodes.F_NEW:

-            case Opcodes.F_FULL:

-                mLocal = Integer.MAX_VALUE;

-                mStack = Integer.MAX_VALUE;

-                break;

-

-            case Opcodes.F_SAME:

-                mLocal = 0;

-                mStack = 0;

-                break;

-

-            case Opcodes.F_SAME1:

-                mLocal = 0;

-                mStack = 1;

-                break;

-

-            case Opcodes.F_APPEND:

-            case Opcodes.F_CHOP:

-                mLocal = 3;

-                mStack = 0;

-                break;

-

-            default:

-                throw new IllegalArgumentException("Invalid frame type " + type);

-        }

-

-        if (nLocal > mLocal) {

-            throw new IllegalArgumentException("Invalid nLocal=" + nLocal

-                    + " for frame type " + type);

-        }

-        if (nStack > mStack) {

-            throw new IllegalArgumentException("Invalid nStack=" + nStack

-                    + " for frame type " + type);

-        }

-

-        if (type != Opcodes.F_CHOP) {

-            if (nLocal > 0 && (local == null || local.length < nLocal)) {

-                throw new IllegalArgumentException("Array local[] is shorter than nLocal");

-            }

-            for (int i = 0; i < nLocal; ++i) {

-                checkFrameValue(local[i]);

-            }

-        }

-        if (nStack > 0 && (stack == null || stack.length < nStack)) {

-            throw new IllegalArgumentException("Array stack[] is shorter than nStack");

-        }

-        for (int i = 0; i < nStack; ++i) {

-            checkFrameValue(stack[i]);

-        }

-

-        mv.visitFrame(type, nLocal, local, nStack, stack);

-    }

-

-    public void visitInsn(final int opcode) {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 0);

-        mv.visitInsn(opcode);

-    }

-

-    public void visitIntInsn(final int opcode, final int operand) {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 1);

-        switch (opcode) {

-            case Opcodes.BIPUSH:

-                checkSignedByte(operand, "Invalid operand");

-                break;

-            case Opcodes.SIPUSH:

-                checkSignedShort(operand, "Invalid operand");

-                break;

-            // case Constants.NEWARRAY:

-            default:

-                if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {

-                    throw new IllegalArgumentException("Invalid operand (must be an array type code T_...): "

-                            + operand);

-                }

-        }

-        mv.visitIntInsn(opcode, operand);

-    }

-

-    public void visitVarInsn(final int opcode, final int var) {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 2);

-        checkUnsignedShort(var, "Invalid variable index");

-        mv.visitVarInsn(opcode, var);

-    }

-

-    public void visitTypeInsn(final int opcode, final String type) {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 3);

-        checkInternalName(type, "type");

-        if (opcode == Opcodes.NEW && type.charAt(0) == '[') {

-            throw new IllegalArgumentException("NEW cannot be used to create arrays: "

-                    + type);

-        }

-        mv.visitTypeInsn(opcode, type);

-    }

-

-    public void visitFieldInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 4);

-        checkInternalName(owner, "owner");

-        checkIdentifier(name, "name");

-        checkDesc(desc, false);

-        mv.visitFieldInsn(opcode, owner, name, desc);

-    }

-

-    public void visitMethodInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 5);

-        checkMethodIdentifier(name, "name");

-        checkInternalName(owner, "owner");

-        checkMethodDesc(desc);

-        mv.visitMethodInsn(opcode, owner, name, desc);

-    }

-

-    public void visitJumpInsn(final int opcode, final Label label) {

-        checkStartCode();

-        checkEndCode();

-        checkOpcode(opcode, 6);

-        checkLabel(label, false, "label");

-        mv.visitJumpInsn(opcode, label);

-    }

-

-    public void visitLabel(final Label label) {

-        checkStartCode();

-        checkEndCode();

-        checkLabel(label, false, "label");

-        if (labels.get(label) != null) {

-            throw new IllegalArgumentException("Already visited label");

-        }

-        labels.put(label, new Integer(labels.size()));

-        mv.visitLabel(label);

-    }

-

-    public void visitLdcInsn(final Object cst) {

-        checkStartCode();

-        checkEndCode();

-        if (!(cst instanceof Type)) {

-            checkConstant(cst);

-        }

-        mv.visitLdcInsn(cst);

-    }

-

-    public void visitIincInsn(final int var, final int increment) {

-        checkStartCode();

-        checkEndCode();

-        checkUnsignedShort(var, "Invalid variable index");

-        checkSignedShort(increment, "Invalid increment");

-        mv.visitIincInsn(var, increment);

-    }

-

-    public void visitTableSwitchInsn(

-        final int min,

-        final int max,

-        final Label dflt,

-        final Label[] labels)

-    {

-        checkStartCode();

-        checkEndCode();

-        if (max < min) {

-            throw new IllegalArgumentException("Max = " + max

-                    + " must be greater than or equal to min = " + min);

-        }

-        checkLabel(dflt, false, "default label");

-        if (labels == null || labels.length != max - min + 1) {

-            throw new IllegalArgumentException("There must be max - min + 1 labels");

-        }

-        for (int i = 0; i < labels.length; ++i) {

-            checkLabel(labels[i], false, "label at index " + i);

-        }

-        mv.visitTableSwitchInsn(min, max, dflt, labels);

-    }

-

-    public void visitLookupSwitchInsn(

-        final Label dflt,

-        final int[] keys,

-        final Label[] labels)

-    {

-        checkEndCode();

-        checkStartCode();

-        checkLabel(dflt, false, "default label");

-        if (keys == null || labels == null || keys.length != labels.length) {

-            throw new IllegalArgumentException("There must be the same number of keys and labels");

-        }

-        for (int i = 0; i < labels.length; ++i) {

-            checkLabel(labels[i], false, "label at index " + i);

-        }

-        mv.visitLookupSwitchInsn(dflt, keys, labels);

-    }

-

-    public void visitMultiANewArrayInsn(final String desc, final int dims) {

-        checkStartCode();

-        checkEndCode();

-        checkDesc(desc, false);

-        if (desc.charAt(0) != '[') {

-            throw new IllegalArgumentException("Invalid descriptor (must be an array type descriptor): "

-                    + desc);

-        }

-        if (dims < 1) {

-            throw new IllegalArgumentException("Invalid dimensions (must be greater than 0): "

-                    + dims);

-        }

-        if (dims > desc.lastIndexOf('[') + 1) {

-            throw new IllegalArgumentException("Invalid dimensions (must not be greater than dims(desc)): "

-                    + dims);

-        }

-        mv.visitMultiANewArrayInsn(desc, dims);

-    }

-

-    public void visitTryCatchBlock(

-        final Label start,

-        final Label end,

-        final Label handler,

-        final String type)

-    {

-        checkStartCode();

-        checkEndCode();

-        if (type != null) {

-            checkInternalName(type, "type");

-        }

-        mv.visitTryCatchBlock(start, end, handler, type);

-    }

-

-    public void visitLocalVariable(

-        final String name,

-        final String desc,

-        final String signature,

-        final Label start,

-        final Label end,

-        final int index)

-    {

-        checkStartCode();

-        checkEndCode();

-        checkIdentifier(name, "name");

-        checkDesc(desc, false);

-        checkLabel(start, true, "start label");

-        checkLabel(end, true, "end label");

-        checkUnsignedShort(index, "Invalid variable index");

-        int s = ((Integer) labels.get(start)).intValue();

-        int e = ((Integer) labels.get(end)).intValue();

-        if (e < s) {

-            throw new IllegalArgumentException("Invalid start and end labels (end must be greater than start)");

-        }

-        mv.visitLocalVariable(name, desc, signature, start, end, index);

-    }

-

-    public void visitLineNumber(final int line, final Label start) {

-        checkStartCode();

-        checkEndCode();

-        checkUnsignedShort(line, "Invalid line number");

-        checkLabel(start, true, "start label");

-        mv.visitLineNumber(line, start);

-    }

-

-    public void visitMaxs(final int maxStack, final int maxLocals) {

-        checkStartCode();

-        checkEndCode();

-        endCode = true;

-        checkUnsignedShort(maxStack, "Invalid max stack");

-        checkUnsignedShort(maxLocals, "Invalid max locals");

-        mv.visitMaxs(maxStack, maxLocals);

-    }

-

-    public void visitEnd() {

-        checkEndMethod();

-        endMethod = true;

-        mv.visitEnd();

-    }

-

-    // -------------------------------------------------------------------------

-

-    /**

-     * Checks that the visitCode method has been called.

-     */

-    void checkStartCode() {

-        if (!startCode) {

-            throw new IllegalStateException("Cannot visit instructions before visitCode has been called.");

-        }

-    }

-

-    /**

-     * Checks that the visitMaxs method has not been called.

-     */

-    void checkEndCode() {

-        if (endCode) {

-            throw new IllegalStateException("Cannot visit instructions after visitMaxs has been called.");

-        }

-    }

-

-    /**

-     * Checks that the visitEnd method has not been called.

-     */

-    void checkEndMethod() {

-        if (endMethod) {

-            throw new IllegalStateException("Cannot visit elements after visitEnd has been called.");

-        }

-    }

-

-    /**

-     * Checks a stack frame value.

-     * 

-     * @param value the value to be checked.

-     */

-    static void checkFrameValue(final Object value) {

-        if (value == Opcodes.TOP || value == Opcodes.INTEGER

-                || value == Opcodes.FLOAT || value == Opcodes.LONG

-                || value == Opcodes.DOUBLE || value == Opcodes.NULL

-                || value == Opcodes.UNINITIALIZED_THIS)

-        {

-            return;

-        }

-        if (value instanceof String) {

-            checkInternalName((String) value, "Invalid stack frame value");

-            return;

-        }

-        if (!(value instanceof Label)) {

-            throw new IllegalArgumentException("Invalid stack frame value: "

-                    + value);

-        }

-    }

-

-    /**

-     * Checks that the type of the given opcode is equal to the given type.

-     * 

-     * @param opcode the opcode to be checked.

-     * @param type the expected opcode type.

-     */

-    static void checkOpcode(final int opcode, final int type) {

-        if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {

-            throw new IllegalArgumentException("Invalid opcode: " + opcode);

-        }

-    }

-

-    /**

-     * Checks that the given value is a signed byte.

-     * 

-     * @param value the value to be checked.

-     * @param msg an message to be used in case of error.

-     */

-    static void checkSignedByte(final int value, final String msg) {

-        if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {

-            throw new IllegalArgumentException(msg

-                    + " (must be a signed byte): " + value);

-        }

-    }

-

-    /**

-     * Checks that the given value is a signed short.

-     * 

-     * @param value the value to be checked.

-     * @param msg an message to be used in case of error.

-     */

-    static void checkSignedShort(final int value, final String msg) {

-        if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {

-            throw new IllegalArgumentException(msg

-                    + " (must be a signed short): " + value);

-        }

-    }

-

-    /**

-     * Checks that the given value is an unsigned short.

-     * 

-     * @param value the value to be checked.

-     * @param msg an message to be used in case of error.

-     */

-    static void checkUnsignedShort(final int value, final String msg) {

-        if (value < 0 || value > 65535) {

-            throw new IllegalArgumentException(msg

-                    + " (must be an unsigned short): " + value);

-        }

-    }

-

-    /**

-     * Checks that the given value is an {@link Integer}, a{@link Float}, a

-     * {@link Long}, a {@link Double} or a {@link String}.

-     * 

-     * @param cst the value to be checked.

-     */

-    static void checkConstant(final Object cst) {

-        if (!(cst instanceof Integer) && !(cst instanceof Float)

-                && !(cst instanceof Long) && !(cst instanceof Double)

-                && !(cst instanceof String))

-        {

-            throw new IllegalArgumentException("Invalid constant: " + cst);

-        }

-    }

-

-    /**

-     * Checks that the given string is a valid Java identifier.

-     * 

-     * @param name the string to be checked.

-     * @param msg a message to be used in case of error.

-     */

-    static void checkIdentifier(final String name, final String msg) {

-        checkIdentifier(name, 0, -1, msg);

-    }

-

-    /**

-     * Checks that the given substring is a valid Java identifier.

-     * 

-     * @param name the string to be checked.

-     * @param start index of the first character of the identifier (inclusive).

-     * @param end index of the last character of the identifier (exclusive). -1

-     *        is equivalent to <tt>name.length()</tt> if name is not

-     *        <tt>null</tt>.

-     * @param msg a message to be used in case of error.

-     */

-    static void checkIdentifier(

-        final String name,

-        final int start,

-        final int end,

-        final String msg)

-    {

-        if (name == null || (end == -1 ? name.length() <= start : end <= start))

-        {

-            throw new IllegalArgumentException("Invalid " + msg

-                    + " (must not be null or empty)");

-        }

-        if (!Character.isJavaIdentifierStart(name.charAt(start))) {

-            throw new IllegalArgumentException("Invalid " + msg

-                    + " (must be a valid Java identifier): " + name);

-        }

-        int max = end == -1 ? name.length() : end;

-        for (int i = start + 1; i < max; ++i) {

-            if (!Character.isJavaIdentifierPart(name.charAt(i))) {

-                throw new IllegalArgumentException("Invalid " + msg

-                        + " (must be a valid Java identifier): " + name);

-            }

-        }

-    }

-

-    /**

-     * Checks that the given string is a valid Java identifier or is equal to

-     * '&lt;init&gt;' or '&lt;clinit&gt;'.

-     * 

-     * @param name the string to be checked.

-     * @param msg a message to be used in case of error.

-     */

-    static void checkMethodIdentifier(final String name, final String msg) {

-        if (name == null || name.length() == 0) {

-            throw new IllegalArgumentException("Invalid " + msg

-                    + " (must not be null or empty)");

-        }

-        if ("<init>".equals(name) || "<clinit>".equals(name)) {

-            return;

-        }

-        if (!Character.isJavaIdentifierStart(name.charAt(0))) {

-            throw new IllegalArgumentException("Invalid "

-                    + msg

-                    + " (must be a '<init>', '<clinit>' or a valid Java identifier): "

-                    + name);

-        }

-        for (int i = 1; i < name.length(); ++i) {

-            if (!Character.isJavaIdentifierPart(name.charAt(i))) {

-                throw new IllegalArgumentException("Invalid "

-                        + msg

-                        + " (must be '<init>' or '<clinit>' or a valid Java identifier): "

-                        + name);

-            }

-        }

-    }

-

-    /**

-     * Checks that the given string is a valid internal class name.

-     * 

-     * @param name the string to be checked.

-     * @param msg a message to be used in case of error.

-     */

-    static void checkInternalName(final String name, final String msg) {

-        if (name == null || name.length() == 0) {

-            throw new IllegalArgumentException("Invalid " + msg

-                    + " (must not be null or empty)");

-        }

-        if (name.charAt(0) == '[') {

-            checkDesc(name, false);

-        } else {

-            checkInternalName(name, 0, -1, msg);

-        }

-    }

-

-    /**

-     * Checks that the given substring is a valid internal class name.

-     * 

-     * @param name the string to be checked.

-     * @param start index of the first character of the identifier (inclusive).

-     * @param end index of the last character of the identifier (exclusive). -1

-     *        is equivalent to <tt>name.length()</tt> if name is not

-     *        <tt>null</tt>.

-     * @param msg a message to be used in case of error.

-     */

-    static void checkInternalName(

-        final String name,

-        final int start,

-        final int end,

-        final String msg)

-    {

-        int max = end == -1 ? name.length() : end;

-        try {

-            int begin = start;

-            int slash;

-            do {

-                slash = name.indexOf('/', begin + 1);

-                if (slash == -1 || slash > max) {

-                    slash = max;

-                }

-                checkIdentifier(name, begin, slash, null);

-                begin = slash + 1;

-            } while (slash != max);

-        } catch (IllegalArgumentException _) {

-            throw new IllegalArgumentException("Invalid "

-                    + msg

-                    + " (must be a fully qualified class name in internal form): "

-                    + name);

-        }

-    }

-

-    /**

-     * Checks that the given string is a valid type descriptor.

-     * 

-     * @param desc the string to be checked.

-     * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.

-     */

-    static void checkDesc(final String desc, final boolean canBeVoid) {

-        int end = checkDesc(desc, 0, canBeVoid);

-        if (end != desc.length()) {

-            throw new IllegalArgumentException("Invalid descriptor: " + desc);

-        }

-    }

-

-    /**

-     * Checks that a the given substring is a valid type descriptor.

-     * 

-     * @param desc the string to be checked.

-     * @param start index of the first character of the identifier (inclusive).

-     * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.

-     * @return the index of the last character of the type decriptor, plus one.

-     */

-    static int checkDesc(

-        final String desc,

-        final int start,

-        final boolean canBeVoid)

-    {

-        if (desc == null || start >= desc.length()) {

-            throw new IllegalArgumentException("Invalid type descriptor (must not be null or empty)");

-        }

-        int index;

-        switch (desc.charAt(start)) {

-            case 'V':

-                if (canBeVoid) {

-                    return start + 1;

-                } else {

-                    throw new IllegalArgumentException("Invalid descriptor: "

-                            + desc);

-                }

-            case 'Z':

-            case 'C':

-            case 'B':

-            case 'S':

-            case 'I':

-            case 'F':

-            case 'J':

-            case 'D':

-                return start + 1;

-            case '[':

-                index = start + 1;

-                while (index < desc.length() && desc.charAt(index) == '[') {

-                    ++index;

-                }

-                if (index < desc.length()) {

-                    return checkDesc(desc, index, false);

-                } else {

-                    throw new IllegalArgumentException("Invalid descriptor: "

-                            + desc);

-                }

-            case 'L':

-                index = desc.indexOf(';', start);

-                if (index == -1 || index - start < 2) {

-                    throw new IllegalArgumentException("Invalid descriptor: "

-                            + desc);

-                }

-                try {

-                    checkInternalName(desc, start + 1, index, null);

-                } catch (IllegalArgumentException _) {

-                    throw new IllegalArgumentException("Invalid descriptor: "

-                            + desc);

-                }

-                return index + 1;

-            default:

-                throw new IllegalArgumentException("Invalid descriptor: "

-                        + desc);

-        }

-    }

-

-    /**

-     * Checks that the given string is a valid method descriptor.

-     * 

-     * @param desc the string to be checked.

-     */

-    static void checkMethodDesc(final String desc) {

-        if (desc == null || desc.length() == 0) {

-            throw new IllegalArgumentException("Invalid method descriptor (must not be null or empty)");

-        }

-        if (desc.charAt(0) != '(' || desc.length() < 3) {

-            throw new IllegalArgumentException("Invalid descriptor: " + desc);

-        }

-        int start = 1;

-        if (desc.charAt(start) != ')') {

-            do {

-                if (desc.charAt(start) == 'V') {

-                    throw new IllegalArgumentException("Invalid descriptor: "

-                            + desc);

-                }

-                start = checkDesc(desc, start, false);

-            } while (start < desc.length() && desc.charAt(start) != ')');

-        }

-        start = checkDesc(desc, start + 1, true);

-        if (start != desc.length()) {

-            throw new IllegalArgumentException("Invalid descriptor: " + desc);

-        }

-    }

-

-    /**

-     * Checks a class signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     */

-    static void checkClassSignature(final String signature) {

-        // ClassSignature:

-        // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*

-

-        int pos = 0;

-        if (getChar(signature, 0) == '<') {

-            pos = checkFormalTypeParameters(signature, pos);

-        }

-        pos = checkClassTypeSignature(signature, pos);

-        while (getChar(signature, pos) == 'L') {

-            pos = checkClassTypeSignature(signature, pos);

-        }

-        if (pos != signature.length()) {

-            throw new IllegalArgumentException(signature + ": error at index "

-                    + pos);

-        }

-    }

-

-    /**

-     * Checks a method signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     */

-    static void checkMethodSignature(final String signature) {

-        // MethodTypeSignature:

-        // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (

-        // ^ClassTypeSignature | ^TypeVariableSignature )*

-

-        int pos = 0;

-        if (getChar(signature, 0) == '<') {

-            pos = checkFormalTypeParameters(signature, pos);

-        }

-        pos = checkChar('(', signature, pos);

-        while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {

-            pos = checkTypeSignature(signature, pos);

-        }

-        pos = checkChar(')', signature, pos);

-        if (getChar(signature, pos) == 'V') {

-            ++pos;

-        } else {

-            pos = checkTypeSignature(signature, pos);

-        }

-        while (getChar(signature, pos) == '^') {

-            ++pos;

-            if (getChar(signature, pos) == 'L') {

-                pos = checkClassTypeSignature(signature, pos);

-            } else {

-                pos = checkTypeVariableSignature(signature, pos);

-            }

-        }

-        if (pos != signature.length()) {

-            throw new IllegalArgumentException(signature + ": error at index "

-                    + pos);

-        }

-    }

-

-    /**

-     * Checks a field signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     */

-    static void checkFieldSignature(final String signature) {

-        int pos = checkFieldTypeSignature(signature, 0);

-        if (pos != signature.length()) {

-            throw new IllegalArgumentException(signature + ": error at index "

-                    + pos);

-        }

-    }

-

-    /**

-     * Checks the formal type parameters of a class or method signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkFormalTypeParameters(final String signature, int pos)

-    {

-        // FormalTypeParameters:

-        // < FormalTypeParameter+ >

-

-        pos = checkChar('<', signature, pos);

-        pos = checkFormalTypeParameter(signature, pos);

-        while (getChar(signature, pos) != '>') {

-            pos = checkFormalTypeParameter(signature, pos);

-        }

-        return pos + 1;

-    }

-

-    /**

-     * Checks a formal type parameter of a class or method signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkFormalTypeParameter(final String signature, int pos)

-    {

-        // FormalTypeParameter:

-        // Identifier : FieldTypeSignature? (: FieldTypeSignature)*

-

-        pos = checkIdentifier(signature, pos);

-        pos = checkChar(':', signature, pos);

-        if ("L[T".indexOf(getChar(signature, pos)) != -1) {

-            pos = checkFieldTypeSignature(signature, pos);

-        }

-        while (getChar(signature, pos) == ':') {

-            pos = checkFieldTypeSignature(signature, pos + 1);

-        }

-        return pos;

-    }

-

-    /**

-     * Checks a field type signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkFieldTypeSignature(final String signature, int pos)

-    {

-        // FieldTypeSignature:

-        // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature

-        //

-        // ArrayTypeSignature:

-        // [ TypeSignature

-

-        switch (getChar(signature, pos)) {

-            case 'L':

-                return checkClassTypeSignature(signature, pos);

-            case '[':

-                return checkTypeSignature(signature, pos + 1);

-            default:

-                return checkTypeVariableSignature(signature, pos);

-        }

-    }

-

-    /**

-     * Checks a class type signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkClassTypeSignature(final String signature, int pos)

-    {

-        // ClassTypeSignature:

-        // L Identifier ( / Identifier )* TypeArguments? ( . Identifier

-        // TypeArguments? )* ;

-

-        pos = checkChar('L', signature, pos);

-        pos = checkIdentifier(signature, pos);

-        while (getChar(signature, pos) == '/') {

-            pos = checkIdentifier(signature, pos + 1);

-        }

-        if (getChar(signature, pos) == '<') {

-            pos = checkTypeArguments(signature, pos);

-        }

-        while (getChar(signature, pos) == '.') {

-            pos = checkIdentifier(signature, pos + 1);

-            if (getChar(signature, pos) == '<') {

-                pos = checkTypeArguments(signature, pos);

-            }

-        }

-        return checkChar(';', signature, pos);

-    }

-

-    /**

-     * Checks the type arguments in a class type signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkTypeArguments(final String signature, int pos) {

-        // TypeArguments:

-        // < TypeArgument+ >

-

-        pos = checkChar('<', signature, pos);

-        pos = checkTypeArgument(signature, pos);

-        while (getChar(signature, pos) != '>') {

-            pos = checkTypeArgument(signature, pos);

-        }

-        return pos + 1;

-    }

-

-    /**

-     * Checks a type argument in a class type signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkTypeArgument(final String signature, int pos) {

-        // TypeArgument:

-        // * | ( ( + | - )? FieldTypeSignature )

-

-        char c = getChar(signature, pos);

-        if (c == '*') {

-            return pos + 1;

-        } else if (c == '+' || c == '-') {

-            pos++;

-        }

-        return checkFieldTypeSignature(signature, pos);

-    }

-

-    /**

-     * Checks a type variable signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkTypeVariableSignature(

-        final String signature,

-        int pos)

-    {

-        // TypeVariableSignature:

-        // T Identifier ;

-

-        pos = checkChar('T', signature, pos);

-        pos = checkIdentifier(signature, pos);

-        return checkChar(';', signature, pos);

-    }

-

-    /**

-     * Checks a type signature.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkTypeSignature(final String signature, int pos) {

-        // TypeSignature:

-        // Z | C | B | S | I | F | J | D | FieldTypeSignature

-

-        switch (getChar(signature, pos)) {

-            case 'Z':

-            case 'C':

-            case 'B':

-            case 'S':

-            case 'I':

-            case 'F':

-            case 'J':

-            case 'D':

-                return pos + 1;

-            default:

-                return checkFieldTypeSignature(signature, pos);

-        }

-    }

-

-    /**

-     * Checks an identifier.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkIdentifier(final String signature, int pos) {

-        if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {

-            throw new IllegalArgumentException(signature

-                    + ": identifier expected at index " + pos);

-        }

-        ++pos;

-        while (Character.isJavaIdentifierPart(getChar(signature, pos))) {

-            ++pos;

-        }

-        return pos;

-    }

-

-    /**

-     * Checks a single character.

-     * 

-     * @param signature a string containing the signature that must be checked.

-     * @param pos index of first character to be checked.

-     * @return the index of the first character after the checked part.

-     */

-    private static int checkChar(final char c, final String signature, int pos)

-    {

-        if (getChar(signature, pos) == c) {

-            return pos + 1;

-        }

-        throw new IllegalArgumentException(signature + ": '" + c

-                + "' expected at index " + pos);

-    }

-

-    /**

-     * Returns the signature car at the given index.

-     * 

-     * @param signature a signature.

-     * @param pos an index in signature.

-     * @return the character at the given index, or 0 if there is no such

-     *         character.

-     */

-    private static char getChar(final String signature, int pos) {

-        return pos < signature.length() ? signature.charAt(pos) : (char) 0;

-    }

-

-    /**

-     * Checks that the given label is not null. This method can also check that

-     * the label has been visited.

-     * 

-     * @param label the label to be checked.

-     * @param checkVisited <tt>true</tt> to check that the label has been

-     *        visited.

-     * @param msg a message to be used in case of error.

-     */

-    void checkLabel(

-        final Label label,

-        final boolean checkVisited,

-        final String msg)

-    {

-        if (label == null) {

-            throw new IllegalArgumentException("Invalid " + msg

-                    + " (must not be null)");

-        }

-        if (checkVisited && labels.get(label) == null) {

-            throw new IllegalArgumentException("Invalid " + msg

-                    + " (must be visited first)");

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/CheckSignatureAdapter.java b/cglib-and-asm/src/org/mockito/asm/util/CheckSignatureAdapter.java
deleted file mode 100644
index 05e9afb..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/CheckSignatureAdapter.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.signature.SignatureVisitor;

-

-/**

- * A {@link SignatureVisitor} that checks that its methods are properly used.

- * 

- * @author Eric Bruneton

- */

-public class CheckSignatureAdapter implements SignatureVisitor {

-

-    /**

-     * Type to be used to check class signatures. See

-     * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.

-     */

-    public static final int CLASS_SIGNATURE = 0;

-

-    /**

-     * Type to be used to check method signatures. See

-     * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.

-     */

-    public static final int METHOD_SIGNATURE = 1;

-

-    /**

-     * Type to be used to check type signatures.See

-     * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.

-     */

-    public static final int TYPE_SIGNATURE = 2;

-

-    private static final int EMPTY = 1;

-

-    private static final int FORMAL = 2;

-

-    private static final int BOUND = 4;

-

-    private static final int SUPER = 8;

-

-    private static final int PARAM = 16;

-

-    private static final int RETURN = 32;

-

-    private static final int SIMPLE_TYPE = 64;

-

-    private static final int CLASS_TYPE = 128;

-

-    private static final int END = 256;

-

-    /**

-     * Type of the signature to be checked.

-     */

-    private final int type;

-

-    /**

-     * State of the automaton used to check the order of method calls.

-     */

-    private int state;

-

-    /**

-     * <tt>true</tt> if the checked type signature can be 'V'.

-     */

-    private boolean canBeVoid;

-

-    /**

-     * The visitor to which this adapter must delegate calls. May be

-     * <tt>null</tt>.

-     */

-    private final SignatureVisitor sv;

-

-    /**

-     * Creates a new {@link CheckSignatureAdapter} object.

-     * 

-     * @param type the type of signature to be checked. See

-     *        {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and

-     *        {@link #TYPE_SIGNATURE}.

-     * @param sv the visitor to which this adapter must delegate calls. May be

-     *        <tt>null</tt>.

-     */

-    public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {

-        this.type = type;

-        this.state = EMPTY;

-        this.sv = sv;

-    }

-

-    // class and method signatures

-

-    public void visitFormalTypeParameter(final String name) {

-        if (type == TYPE_SIGNATURE

-                || (state != EMPTY && state != FORMAL && state != BOUND))

-        {

-            throw new IllegalStateException();

-        }

-        CheckMethodAdapter.checkIdentifier(name, "formal type parameter");

-        state = FORMAL;

-        if (sv != null) {

-            sv.visitFormalTypeParameter(name);

-        }

-    }

-

-    public SignatureVisitor visitClassBound() {

-        if (state != FORMAL) {

-            throw new IllegalStateException();

-        }

-        state = BOUND;

-        SignatureVisitor v = sv == null ? null : sv.visitClassBound();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    public SignatureVisitor visitInterfaceBound() {

-        if (state != FORMAL && state != BOUND) {

-            throw new IllegalArgumentException();

-        }

-        SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    // class signatures

-

-    public SignatureVisitor visitSuperclass() {

-        if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0)

-        {

-            throw new IllegalArgumentException();

-        }

-        state = SUPER;

-        SignatureVisitor v = sv == null ? null : sv.visitSuperclass();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    public SignatureVisitor visitInterface() {

-        if (state != SUPER) {

-            throw new IllegalStateException();

-        }

-        SignatureVisitor v = sv == null ? null : sv.visitInterface();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    // method signatures

-

-    public SignatureVisitor visitParameterType() {

-        if (type != METHOD_SIGNATURE

-                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)

-        {

-            throw new IllegalArgumentException();

-        }

-        state = PARAM;

-        SignatureVisitor v = sv == null ? null : sv.visitParameterType();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    public SignatureVisitor visitReturnType() {

-        if (type != METHOD_SIGNATURE

-                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)

-        {

-            throw new IllegalArgumentException();

-        }

-        state = RETURN;

-        SignatureVisitor v = sv == null ? null : sv.visitReturnType();

-        CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-        cv.canBeVoid = true;

-        return cv;

-    }

-

-    public SignatureVisitor visitExceptionType() {

-        if (state != RETURN) {

-            throw new IllegalStateException();

-        }

-        SignatureVisitor v = sv == null ? null : sv.visitExceptionType();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    // type signatures

-

-    public void visitBaseType(final char descriptor) {

-        if (type != TYPE_SIGNATURE || state != EMPTY) {

-            throw new IllegalStateException();

-        }

-        if (descriptor == 'V') {

-            if (!canBeVoid) {

-                throw new IllegalArgumentException();

-            }

-        } else {

-            if ("ZCBSIFJD".indexOf(descriptor) == -1) {

-                throw new IllegalArgumentException();

-            }

-        }

-        state = SIMPLE_TYPE;

-        if (sv != null) {

-            sv.visitBaseType(descriptor);

-        }

-    }

-

-    public void visitTypeVariable(final String name) {

-        if (type != TYPE_SIGNATURE || state != EMPTY) {

-            throw new IllegalStateException();

-        }

-        CheckMethodAdapter.checkIdentifier(name, "type variable");

-        state = SIMPLE_TYPE;

-        if (sv != null) {

-            sv.visitTypeVariable(name);

-        }

-    }

-

-    public SignatureVisitor visitArrayType() {

-        if (type != TYPE_SIGNATURE || state != EMPTY) {

-            throw new IllegalStateException();

-        }

-        state = SIMPLE_TYPE;

-        SignatureVisitor v = sv == null ? null : sv.visitArrayType();

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    public void visitClassType(final String name) {

-        if (type != TYPE_SIGNATURE || state != EMPTY) {

-            throw new IllegalStateException();

-        }

-        CheckMethodAdapter.checkInternalName(name, "class name");

-        state = CLASS_TYPE;

-        if (sv != null) {

-            sv.visitClassType(name);

-        }

-    }

-

-    public void visitInnerClassType(final String name) {

-        if (state != CLASS_TYPE) {

-            throw new IllegalStateException();

-        }

-        CheckMethodAdapter.checkIdentifier(name, "inner class name");

-        if (sv != null) {

-            sv.visitInnerClassType(name);

-        }

-    }

-

-    public void visitTypeArgument() {

-        if (state != CLASS_TYPE) {

-            throw new IllegalStateException();

-        }

-        if (sv != null) {

-            sv.visitTypeArgument();

-        }

-    }

-

-    public SignatureVisitor visitTypeArgument(final char wildcard) {

-        if (state != CLASS_TYPE) {

-            throw new IllegalStateException();

-        }

-        if ("+-=".indexOf(wildcard) == -1) {

-            throw new IllegalArgumentException();

-        }

-        SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);

-        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);

-    }

-

-    public void visitEnd() {

-        if (state != CLASS_TYPE) {

-            throw new IllegalStateException();

-        }

-        state = END;

-        if (sv != null) {

-            sv.visitEnd();

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/TraceAbstractVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/TraceAbstractVisitor.java
deleted file mode 100644
index b7173fd..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/TraceAbstractVisitor.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-

-/**

- * An abstract trace visitor.

- * 

- * @author Eric Bruneton

- */

-public abstract class TraceAbstractVisitor extends AbstractVisitor {

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for internal

-     * type names in bytecode notation.

-     */

-    public static final int INTERNAL_NAME = 0;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for field

-     * descriptors, formatted in bytecode notation

-     */

-    public static final int FIELD_DESCRIPTOR = 1;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for field

-     * signatures, formatted in bytecode notation

-     */

-    public static final int FIELD_SIGNATURE = 2;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for method

-     * descriptors, formatted in bytecode notation

-     */

-    public static final int METHOD_DESCRIPTOR = 3;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for method

-     * signatures, formatted in bytecode notation

-     */

-    public static final int METHOD_SIGNATURE = 4;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for class

-     * signatures, formatted in bytecode notation

-     */

-    public static final int CLASS_SIGNATURE = 5;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for field or

-     * method return value signatures, formatted in default Java notation

-     * (non-bytecode)

-     */

-    public static final int TYPE_DECLARATION = 6;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for class

-     * signatures, formatted in default Java notation (non-bytecode)

-     */

-    public static final int CLASS_DECLARATION = 7;

-

-    /**

-     * Constant used in {@link #appendDescriptor appendDescriptor} for method

-     * parameter signatures, formatted in default Java notation (non-bytecode)

-     */

-    public static final int PARAMETERS_DECLARATION = 8;

-

-    /**

-     * Tab for class members.

-     */

-    protected String tab = "  ";

-

-    /**

-     * Prints a disassembled view of the given annotation.

-     * 

-     * @param desc the class descriptor of the annotation class.

-     * @param visible <tt>true</tt> if the annotation is visible at runtime.

-     * @return a visitor to visit the annotation values.

-     */

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        buf.setLength(0);

-        buf.append(tab).append('@');

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append('(');

-        text.add(buf.toString());

-        TraceAnnotationVisitor tav = createTraceAnnotationVisitor();

-        text.add(tav.getText());

-        text.add(visible ? ")\n" : ") // invisible\n");

-        return tav;

-    }

-

-    /**

-     * Prints a disassembled view of the given attribute.

-     * 

-     * @param attr an attribute.

-     */

-    public void visitAttribute(final Attribute attr) {

-        buf.setLength(0);

-        buf.append(tab).append("ATTRIBUTE ");

-        appendDescriptor(-1, attr.type);

-

-        if (attr instanceof Traceable) {

-            ((Traceable) attr).trace(buf, null);

-        } else {

-            buf.append(" : unknown\n");

-        }

-

-        text.add(buf.toString());

-    }

-

-    /**

-     * Does nothing.

-     */

-    public void visitEnd() {

-        // does nothing

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    protected TraceAnnotationVisitor createTraceAnnotationVisitor() {

-        return new TraceAnnotationVisitor();

-    }

-

-    /**

-     * Appends an internal name, a type descriptor or a type signature to

-     * {@link #buf buf}.

-     * 

-     * @param type indicates if desc is an internal name, a field descriptor, a

-     *        method descriptor, a class signature, ...

-     * @param desc an internal name, type descriptor, or type signature. May be

-     *        <tt>null</tt>.

-     */

-    protected void appendDescriptor(final int type, final String desc) {

-        if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE

-                || type == METHOD_SIGNATURE)

-        {

-            if (desc != null) {

-                buf.append("// signature ").append(desc).append('\n');

-            }

-        } else {

-            buf.append(desc);

-        }

-    }

-

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/TraceAnnotationVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/TraceAnnotationVisitor.java
deleted file mode 100644
index 918f88a..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/TraceAnnotationVisitor.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Type;

-

-/**

- * An {@link AnnotationVisitor} that prints a disassembled view of the

- * annotations it visits.

- * 

- * @author Eric Bruneton

- */

-public class TraceAnnotationVisitor extends TraceAbstractVisitor implements

-        AnnotationVisitor

-{

-

-    /**

-     * The {@link AnnotationVisitor} to which this visitor delegates calls. May

-     * be <tt>null</tt>.

-     */

-    protected AnnotationVisitor av;

-

-    private int valueNumber = 0;

-

-    /**

-     * Constructs a new {@link TraceAnnotationVisitor}.

-     */

-    public TraceAnnotationVisitor() {

-        // ignore

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the AnnotationVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(final String name, final Object value) {

-        buf.setLength(0);

-        appendComa(valueNumber++);

-

-        if (name != null) {

-            buf.append(name).append('=');

-        }

-

-        if (value instanceof String) {

-            visitString((String) value);

-        } else if (value instanceof Type) {

-            visitType((Type) value);

-        } else if (value instanceof Byte) {

-            visitByte(((Byte) value).byteValue());

-        } else if (value instanceof Boolean) {

-            visitBoolean(((Boolean) value).booleanValue());

-        } else if (value instanceof Short) {

-            visitShort(((Short) value).shortValue());

-        } else if (value instanceof Character) {

-            visitChar(((Character) value).charValue());

-        } else if (value instanceof Integer) {

-            visitInt(((Integer) value).intValue());

-        } else if (value instanceof Float) {

-            visitFloat(((Float) value).floatValue());

-        } else if (value instanceof Long) {

-            visitLong(((Long) value).longValue());

-        } else if (value instanceof Double) {

-            visitDouble(((Double) value).doubleValue());

-        } else if (value.getClass().isArray()) {

-            buf.append('{');

-            if (value instanceof byte[]) {

-                byte[] v = (byte[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitByte(v[i]);

-                }

-            } else if (value instanceof boolean[]) {

-                boolean[] v = (boolean[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitBoolean(v[i]);

-                }

-            } else if (value instanceof short[]) {

-                short[] v = (short[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitShort(v[i]);

-                }

-            } else if (value instanceof char[]) {

-                char[] v = (char[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitChar(v[i]);

-                }

-            } else if (value instanceof int[]) {

-                int[] v = (int[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitInt(v[i]);

-                }

-            } else if (value instanceof long[]) {

-                long[] v = (long[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitLong(v[i]);

-                }

-            } else if (value instanceof float[]) {

-                float[] v = (float[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitFloat(v[i]);

-                }

-            } else if (value instanceof double[]) {

-                double[] v = (double[]) value;

-                for (int i = 0; i < v.length; i++) {

-                    appendComa(i);

-                    visitDouble(v[i]);

-                }

-            }

-            buf.append('}');

-        }

-

-        text.add(buf.toString());

-

-        if (av != null) {

-            av.visit(name, value);

-        }

-    }

-

-    private void visitInt(final int value) {

-        buf.append(value);

-    }

-

-    private void visitLong(final long value) {

-        buf.append(value).append('L');

-    }

-

-    private void visitFloat(final float value) {

-        buf.append(value).append('F');

-    }

-

-    private void visitDouble(final double value) {

-        buf.append(value).append('D');

-    }

-

-    private void visitChar(final char value) {

-        buf.append("(char)").append((int) value);

-    }

-

-    private void visitShort(final short value) {

-        buf.append("(short)").append(value);

-    }

-

-    private void visitByte(final byte value) {

-        buf.append("(byte)").append(value);

-    }

-

-    private void visitBoolean(final boolean value) {

-        buf.append(value);

-    }

-

-    private void visitString(final String value) {

-        appendString(buf, value);

-    }

-

-    private void visitType(final Type value) {

-        buf.append(value.getClassName()).append(".class");

-    }

-

-    public void visitEnum(

-        final String name,

-        final String desc,

-        final String value)

-    {

-        buf.setLength(0);

-        appendComa(valueNumber++);

-        if (name != null) {

-            buf.append(name).append('=');

-        }

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append('.').append(value);

-        text.add(buf.toString());

-

-        if (av != null) {

-            av.visitEnum(name, desc, value);

-        }

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        appendComa(valueNumber++);

-        if (name != null) {

-            buf.append(name).append('=');

-        }

-        buf.append('@');

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append('(');

-        text.add(buf.toString());

-        TraceAnnotationVisitor tav = createTraceAnnotationVisitor();

-        text.add(tav.getText());

-        text.add(")");

-        if (av != null) {

-            tav.av = av.visitAnnotation(name, desc);

-        }

-        return tav;

-    }

-

-    public AnnotationVisitor visitArray(final String name) {

-        buf.setLength(0);

-        appendComa(valueNumber++);

-        if (name != null) {

-            buf.append(name).append('=');

-        }

-        buf.append('{');

-        text.add(buf.toString());

-        TraceAnnotationVisitor tav = createTraceAnnotationVisitor();

-        text.add(tav.getText());

-        text.add("}");

-        if (av != null) {

-            tav.av = av.visitArray(name);

-        }

-        return tav;

-    }

-

-    public void visitEnd() {

-        if (av != null) {

-            av.visitEnd();

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    private void appendComa(final int i) {

-        if (i != 0) {

-            buf.append(", ");

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/TraceClassVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/TraceClassVisitor.java
deleted file mode 100644
index aec353e..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/TraceClassVisitor.java
+++ /dev/null
@@ -1,523 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import java.io.FileInputStream;

-import java.io.PrintWriter;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.ClassReader;

-import org.mockito.asm.ClassVisitor;

-import org.mockito.asm.FieldVisitor;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.signature.SignatureReader;

-

-/**

- * A {@link ClassVisitor} that prints a disassembled view of the classes it

- * visits. This class visitor can be used alone (see the {@link #main main}

- * method) to disassemble a class. It can also be used in the middle of class

- * visitor chain to trace the class that is visited at a given point in this

- * chain. This may be uselful for debugging purposes. <p> The trace printed when

- * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>

- * 

- * <pre>

- * // class version 49.0 (49)

- * // access flags 33

- * public class Hello {

- *

- *  // compiled from: Hello.java

- *

- *   // access flags 1

- *   public &lt;init&gt; ()V

- *     ALOAD 0

- *     INVOKESPECIAL java/lang/Object &lt;init&gt; ()V

- *     RETURN

- *     MAXSTACK = 1

- *     MAXLOCALS = 1

- *

- *   // access flags 9

- *   public static main ([Ljava/lang/String;)V

- *     GETSTATIC java/lang/System out Ljava/io/PrintStream;

- *     LDC &quot;hello&quot;

- *     INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V

- *     RETURN

- *     MAXSTACK = 2

- *     MAXLOCALS = 1

- * }

- * </pre>

- * 

- * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>

- * 

- * <pre>

- * public class Hello {

- *

- *     public static void main(String[] args) {

- *         System.out.println(&quot;hello&quot;);

- *     }

- * }

- * </pre>

- * 

- * </blockquote>

- * 

- * @author Eric Bruneton

- * @author Eugene Kuleshov

- */

-public class TraceClassVisitor extends TraceAbstractVisitor implements

-        ClassVisitor

-{

-

-    /**

-     * The {@link ClassVisitor} to which this visitor delegates calls. May be

-     * <tt>null</tt>.

-     */

-    protected final ClassVisitor cv;

-

-    /**

-     * The print writer to be used to print the class.

-     */

-    protected final PrintWriter pw;

-

-    /**

-     * Prints a disassembled view of the given class to the standard output. <p>

-     * Usage: TraceClassVisitor [-debug] &lt;fully qualified class name or class

-     * file name &gt;

-     * 

-     * @param args the command line arguments.

-     * 

-     * @throws Exception if the class cannot be found, or if an IO exception

-     *         occurs.

-     */

-    public static void main(final String[] args) throws Exception {

-        int i = 0;

-        int flags = ClassReader.SKIP_DEBUG;

-

-        boolean ok = true;

-        if (args.length < 1 || args.length > 2) {

-            ok = false;

-        }

-        if (ok && "-debug".equals(args[0])) {

-            i = 1;

-            flags = 0;

-            if (args.length != 2) {

-                ok = false;

-            }

-        }

-        if (!ok) {

-            System.err.println("Prints a disassembled view of the given class.");

-            System.err.println("Usage: TraceClassVisitor [-debug] "

-                    + "<fully qualified class name or class file name>");

-            return;

-        }

-        ClassReader cr;

-        if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1

-                || args[i].indexOf('/') > -1)

-        {

-            cr = new ClassReader(new FileInputStream(args[i]));

-        } else {

-            cr = new ClassReader(args[i]);

-        }

-        cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),

-                getDefaultAttributes(),

-                flags);

-    }

-

-    /**

-     * Constructs a new {@link TraceClassVisitor}.

-     * 

-     * @param pw the print writer to be used to print the class.

-     */

-    public TraceClassVisitor(final PrintWriter pw) {

-        this(null, pw);

-    }

-

-    /**

-     * Constructs a new {@link TraceClassVisitor}.

-     * 

-     * @param cv the {@link ClassVisitor} to which this visitor delegates calls.

-     *        May be <tt>null</tt>.

-     * @param pw the print writer to be used to print the class.

-     */

-    public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {

-        this.cv = cv;

-        this.pw = pw;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the ClassVisitor interface

-    // ------------------------------------------------------------------------

-

-    public void visit(

-        final int version,

-        final int access,

-        final String name,

-        final String signature,

-        final String superName,

-        final String[] interfaces)

-    {

-        int major = version & 0xFFFF;

-        int minor = version >>> 16;

-        buf.setLength(0);

-        buf.append("// class version ")

-                .append(major)

-                .append('.')

-                .append(minor)

-                .append(" (")

-                .append(version)

-                .append(")\n");

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            buf.append("// DEPRECATED\n");

-        }

-        buf.append("// access flags ").append(access).append('\n');

-

-        appendDescriptor(CLASS_SIGNATURE, signature);

-        if (signature != null) {

-            TraceSignatureVisitor sv = new TraceSignatureVisitor(access);

-            SignatureReader r = new SignatureReader(signature);

-            r.accept(sv);

-            buf.append("// declaration: ")

-                    .append(name)

-                    .append(sv.getDeclaration())

-                    .append('\n');

-        }

-

-        appendAccess(access & ~Opcodes.ACC_SUPER);

-        if ((access & Opcodes.ACC_ANNOTATION) != 0) {

-            buf.append("@interface ");

-        } else if ((access & Opcodes.ACC_INTERFACE) != 0) {

-            buf.append("interface ");

-        } else if ((access & Opcodes.ACC_ENUM) == 0) {

-            buf.append("class ");

-        }

-        appendDescriptor(INTERNAL_NAME, name);

-

-        if (superName != null && !"java/lang/Object".equals(superName)) {

-            buf.append(" extends ");

-            appendDescriptor(INTERNAL_NAME, superName);

-            buf.append(' ');

-        }

-        if (interfaces != null && interfaces.length > 0) {

-            buf.append(" implements ");

-            for (int i = 0; i < interfaces.length; ++i) {

-                appendDescriptor(INTERNAL_NAME, interfaces[i]);

-                buf.append(' ');

-            }

-        }

-        buf.append(" {\n\n");

-

-        text.add(buf.toString());

-

-        if (cv != null) {

-            cv.visit(version, access, name, signature, superName, interfaces);

-        }

-    }

-

-    public void visitSource(final String file, final String debug) {

-        buf.setLength(0);

-        if (file != null) {

-            buf.append(tab)

-                    .append("// compiled from: ")

-                    .append(file)

-                    .append('\n');

-        }

-        if (debug != null) {

-            buf.append(tab)

-                    .append("// debug info: ")

-                    .append(debug)

-                    .append('\n');

-        }

-        if (buf.length() > 0) {

-            text.add(buf.toString());

-        }

-

-        if (cv != null) {

-            cv.visitSource(file, debug);

-        }

-    }

-

-    public void visitOuterClass(

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append(tab).append("OUTERCLASS ");

-        appendDescriptor(INTERNAL_NAME, owner);

-        buf.append(' ');

-        if (name != null) {

-            buf.append(name).append(' ');

-        }

-        appendDescriptor(METHOD_DESCRIPTOR, desc);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (cv != null) {

-            cv.visitOuterClass(owner, name, desc);

-        }

-    }

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        text.add("\n");

-        AnnotationVisitor tav = super.visitAnnotation(desc, visible);

-        if (cv != null) {

-            ((TraceAnnotationVisitor) tav).av = cv.visitAnnotation(desc,

-                    visible);

-        }

-        return tav;

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        text.add("\n");

-        super.visitAttribute(attr);

-

-        if (cv != null) {

-            cv.visitAttribute(attr);

-        }

-    }

-

-    public void visitInnerClass(

-        final String name,

-        final String outerName,

-        final String innerName,

-        final int access)

-    {

-        buf.setLength(0);

-        buf.append(tab).append("// access flags ");

-        buf.append(access & ~Opcodes.ACC_SUPER).append('\n');

-        buf.append(tab);

-        appendAccess(access);

-        buf.append("INNERCLASS ");

-        appendDescriptor(INTERNAL_NAME, name);

-        buf.append(' ');

-        appendDescriptor(INTERNAL_NAME, outerName);

-        buf.append(' ');

-        appendDescriptor(INTERNAL_NAME, innerName);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (cv != null) {

-            cv.visitInnerClass(name, outerName, innerName, access);

-        }

-    }

-

-    public FieldVisitor visitField(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final Object value)

-    {

-        buf.setLength(0);

-        buf.append('\n');

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            buf.append(tab).append("// DEPRECATED\n");

-        }

-        buf.append(tab).append("// access flags ").append(access).append('\n');

-        if (signature != null) {

-            buf.append(tab);

-            appendDescriptor(FIELD_SIGNATURE, signature);

-

-            TraceSignatureVisitor sv = new TraceSignatureVisitor(0);

-            SignatureReader r = new SignatureReader(signature);

-            r.acceptType(sv);

-            buf.append(tab)

-                    .append("// declaration: ")

-                    .append(sv.getDeclaration())

-                    .append('\n');

-        }

-

-        buf.append(tab);

-        appendAccess(access);

-

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append(' ').append(name);

-        if (value != null) {

-            buf.append(" = ");

-            if (value instanceof String) {

-                buf.append('\"').append(value).append('\"');

-            } else {

-                buf.append(value);

-            }

-        }

-

-        buf.append('\n');

-        text.add(buf.toString());

-

-        TraceFieldVisitor tav = createTraceFieldVisitor();

-        text.add(tav.getText());

-

-        if (cv != null) {

-            tav.fv = cv.visitField(access, name, desc, signature, value);

-        }

-

-        return tav;

-    }

-

-    public MethodVisitor visitMethod(

-        final int access,

-        final String name,

-        final String desc,

-        final String signature,

-        final String[] exceptions)

-    {

-        buf.setLength(0);

-        buf.append('\n');

-        if ((access & Opcodes.ACC_DEPRECATED) != 0) {

-            buf.append(tab).append("// DEPRECATED\n");

-        }

-        buf.append(tab).append("// access flags ").append(access).append('\n');

-

-        if (signature != null) {

-            buf.append(tab);

-            appendDescriptor(METHOD_SIGNATURE, signature);

-

-            TraceSignatureVisitor v = new TraceSignatureVisitor(0);

-            SignatureReader r = new SignatureReader(signature);

-            r.accept(v);

-            String genericDecl = v.getDeclaration();

-            String genericReturn = v.getReturnType();

-            String genericExceptions = v.getExceptions();

-

-            buf.append(tab)

-                    .append("// declaration: ")

-                    .append(genericReturn)

-                    .append(' ')

-                    .append(name)

-                    .append(genericDecl);

-            if (genericExceptions != null) {

-                buf.append(" throws ").append(genericExceptions);

-            }

-            buf.append('\n');

-        }

-

-        buf.append(tab);

-        appendAccess(access);

-        if ((access & Opcodes.ACC_NATIVE) != 0) {

-            buf.append("native ");

-        }

-        if ((access & Opcodes.ACC_VARARGS) != 0) {

-            buf.append("varargs ");

-        }

-        if ((access & Opcodes.ACC_BRIDGE) != 0) {

-            buf.append("bridge ");

-        }

-

-        buf.append(name);

-        appendDescriptor(METHOD_DESCRIPTOR, desc);

-        if (exceptions != null && exceptions.length > 0) {

-            buf.append(" throws ");

-            for (int i = 0; i < exceptions.length; ++i) {

-                appendDescriptor(INTERNAL_NAME, exceptions[i]);

-                buf.append(' ');

-            }

-        }

-

-        buf.append('\n');

-        text.add(buf.toString());

-

-        TraceMethodVisitor tcv = createTraceMethodVisitor();

-        text.add(tcv.getText());

-

-        if (cv != null) {

-            tcv.mv = cv.visitMethod(access, name, desc, signature, exceptions);

-        }

-

-        return tcv;

-    }

-

-    public void visitEnd() {

-        text.add("}\n");

-

-        print(pw);

-        pw.flush();

-

-        if (cv != null) {

-            cv.visitEnd();

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    protected TraceFieldVisitor createTraceFieldVisitor() {

-        return new TraceFieldVisitor();

-    }

-

-    protected TraceMethodVisitor createTraceMethodVisitor() {

-        return new TraceMethodVisitor();

-    }

-

-    /**

-     * Appends a string representation of the given access modifiers to {@link

-     * #buf buf}.

-     * 

-     * @param access some access modifiers.

-     */

-    private void appendAccess(final int access) {

-        if ((access & Opcodes.ACC_PUBLIC) != 0) {

-            buf.append("public ");

-        }

-        if ((access & Opcodes.ACC_PRIVATE) != 0) {

-            buf.append("private ");

-        }

-        if ((access & Opcodes.ACC_PROTECTED) != 0) {

-            buf.append("protected ");

-        }

-        if ((access & Opcodes.ACC_FINAL) != 0) {

-            buf.append("final ");

-        }

-        if ((access & Opcodes.ACC_STATIC) != 0) {

-            buf.append("static ");

-        }

-        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {

-            buf.append("synchronized ");

-        }

-        if ((access & Opcodes.ACC_VOLATILE) != 0) {

-            buf.append("volatile ");

-        }

-        if ((access & Opcodes.ACC_TRANSIENT) != 0) {

-            buf.append("transient ");

-        }

-        if ((access & Opcodes.ACC_ABSTRACT) != 0) {

-            buf.append("abstract ");

-        }

-        if ((access & Opcodes.ACC_STRICT) != 0) {

-            buf.append("strictfp ");

-        }

-        if ((access & Opcodes.ACC_ENUM) != 0) {

-            buf.append("enum ");

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/TraceFieldVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/TraceFieldVisitor.java
deleted file mode 100644
index a384350..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/TraceFieldVisitor.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.FieldVisitor;

-

-/**

- * A {@link FieldVisitor} that prints a disassembled view of the fields it

- * visits.

- * 

- * @author Eric Bruneton

- */

-public class TraceFieldVisitor extends TraceAbstractVisitor implements

-        FieldVisitor

-{

-

-    /**

-     * The {@link FieldVisitor} to which this visitor delegates calls. May be

-     * <tt>null</tt>.

-     */

-    protected FieldVisitor fv;

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        AnnotationVisitor av = super.visitAnnotation(desc, visible);

-        if (fv != null) {

-            ((TraceAnnotationVisitor) av).av = fv.visitAnnotation(desc, visible);

-        }

-        return av;

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        super.visitAttribute(attr);

-

-        if (fv != null) {

-            fv.visitAttribute(attr);

-        }

-    }

-

-    public void visitEnd() {

-        super.visitEnd();

-

-        if (fv != null) {

-            fv.visitEnd();

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/TraceMethodVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/TraceMethodVisitor.java
deleted file mode 100644
index 9b5faa6..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/TraceMethodVisitor.java
+++ /dev/null
@@ -1,567 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.AnnotationVisitor;

-import org.mockito.asm.Attribute;

-import org.mockito.asm.Label;

-import org.mockito.asm.MethodVisitor;

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.Type;

-import org.mockito.asm.signature.SignatureReader;

-

-import java.util.HashMap;

-import java.util.Map;

-

-/**

- * A {@link MethodVisitor} that prints a disassembled view of the methods it

- * visits.

- * 

- * @author Eric Bruneton

- */

-public class TraceMethodVisitor extends TraceAbstractVisitor implements

-        MethodVisitor

-{

-

-    /**

-     * The {@link MethodVisitor} to which this visitor delegates calls. May be

-     * <tt>null</tt>.

-     */

-    protected MethodVisitor mv;

-

-    /**

-     * Tab for bytecode instructions.

-     */

-    protected String tab2 = "    ";

-

-    /**

-     * Tab for table and lookup switch instructions.

-     */

-    protected String tab3 = "      ";

-

-    /**

-     * Tab for labels.

-     */

-    protected String ltab = "   ";

-

-    /**

-     * The label names. This map associate String values to Label keys.

-     */

-    protected final Map labelNames;

-

-    /**

-     * Constructs a new {@link TraceMethodVisitor}.

-     */

-    public TraceMethodVisitor() {

-        this(null);

-    }

-

-    /**

-     * Constructs a new {@link TraceMethodVisitor}.

-     * 

-     * @param mv the {@link MethodVisitor} to which this visitor delegates

-     *        calls. May be <tt>null</tt>.

-     */

-    public TraceMethodVisitor(final MethodVisitor mv) {

-        this.labelNames = new HashMap();

-        this.mv = mv;

-    }

-

-    // ------------------------------------------------------------------------

-    // Implementation of the MethodVisitor interface

-    // ------------------------------------------------------------------------

-

-    public AnnotationVisitor visitAnnotation(

-        final String desc,

-        final boolean visible)

-    {

-        AnnotationVisitor av = super.visitAnnotation(desc, visible);

-        if (mv != null) {

-            ((TraceAnnotationVisitor) av).av = mv.visitAnnotation(desc, visible);

-        }

-        return av;

-    }

-

-    public void visitAttribute(final Attribute attr) {

-        buf.setLength(0);

-        buf.append(tab).append("ATTRIBUTE ");

-        appendDescriptor(-1, attr.type);

-

-        if (attr instanceof Traceable) {

-            ((Traceable) attr).trace(buf, labelNames);

-        } else {

-            buf.append(" : unknown\n");

-        }

-

-        text.add(buf.toString());

-        if (mv != null) {

-            mv.visitAttribute(attr);

-        }

-    }

-

-    public AnnotationVisitor visitAnnotationDefault() {

-        text.add(tab2 + "default=");

-        TraceAnnotationVisitor tav = createTraceAnnotationVisitor();

-        text.add(tav.getText());

-        text.add("\n");

-        if (mv != null) {

-            tav.av = mv.visitAnnotationDefault();

-        }

-        return tav;

-    }

-

-    public AnnotationVisitor visitParameterAnnotation(

-        final int parameter,

-        final String desc,

-        final boolean visible)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append('@');

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append('(');

-        text.add(buf.toString());

-        TraceAnnotationVisitor tav = createTraceAnnotationVisitor();

-        text.add(tav.getText());

-        text.add(visible ? ") // parameter " : ") // invisible, parameter ");

-        text.add(new Integer(parameter));

-        text.add("\n");

-        if (mv != null) {

-            tav.av = mv.visitParameterAnnotation(parameter, desc, visible);

-        }

-        return tav;

-    }

-

-    public void visitCode() {

-        if (mv != null) {

-            mv.visitCode();

-        }

-    }

-

-    public void visitFrame(

-        final int type,

-        final int nLocal,

-        final Object[] local,

-        final int nStack,

-        final Object[] stack)

-    {

-        buf.setLength(0);

-        buf.append(ltab);

-        buf.append("FRAME ");

-        switch (type) {

-            case Opcodes.F_NEW:

-            case Opcodes.F_FULL:

-                buf.append("FULL [");

-                appendFrameTypes(nLocal, local);

-                buf.append("] [");

-                appendFrameTypes(nStack, stack);

-                buf.append(']');

-                break;

-            case Opcodes.F_APPEND:

-                buf.append("APPEND [");

-                appendFrameTypes(nLocal, local);

-                buf.append(']');

-                break;

-            case Opcodes.F_CHOP:

-                buf.append("CHOP ").append(nLocal);

-                break;

-            case Opcodes.F_SAME:

-                buf.append("SAME");

-                break;

-            case Opcodes.F_SAME1:

-                buf.append("SAME1 ");

-                appendFrameTypes(1, stack);

-                break;

-        }

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitFrame(type, nLocal, local, nStack, stack);

-        }

-    }

-

-    public void visitInsn(final int opcode) {

-        buf.setLength(0);

-        buf.append(tab2).append(OPCODES[opcode]).append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitInsn(opcode);

-        }

-    }

-

-    public void visitIntInsn(final int opcode, final int operand) {

-        buf.setLength(0);

-        buf.append(tab2)

-                .append(OPCODES[opcode])

-                .append(' ')

-                .append(opcode == Opcodes.NEWARRAY

-                        ? TYPES[operand]

-                        : Integer.toString(operand))

-                .append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitIntInsn(opcode, operand);

-        }

-    }

-

-    public void visitVarInsn(final int opcode, final int var) {

-        buf.setLength(0);

-        buf.append(tab2)

-                .append(OPCODES[opcode])

-                .append(' ')

-                .append(var)

-                .append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitVarInsn(opcode, var);

-        }

-    }

-

-    public void visitTypeInsn(final int opcode, final String type) {

-        buf.setLength(0);

-        buf.append(tab2).append(OPCODES[opcode]).append(' ');

-        appendDescriptor(INTERNAL_NAME, type);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitTypeInsn(opcode, type);

-        }

-    }

-

-    public void visitFieldInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append(OPCODES[opcode]).append(' ');

-        appendDescriptor(INTERNAL_NAME, owner);

-        buf.append('.').append(name).append(" : ");

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitFieldInsn(opcode, owner, name, desc);

-        }

-    }

-

-    public void visitMethodInsn(

-        final int opcode,

-        final String owner,

-        final String name,

-        final String desc)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append(OPCODES[opcode]).append(' ');

-        appendDescriptor(INTERNAL_NAME, owner);

-        buf.append('.').append(name).append(' ');

-        appendDescriptor(METHOD_DESCRIPTOR, desc);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitMethodInsn(opcode, owner, name, desc);

-        }

-    }

-

-    public void visitJumpInsn(final int opcode, final Label label) {

-        buf.setLength(0);

-        buf.append(tab2).append(OPCODES[opcode]).append(' ');

-        appendLabel(label);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitJumpInsn(opcode, label);

-        }

-    }

-

-    public void visitLabel(final Label label) {

-        buf.setLength(0);

-        buf.append(ltab);

-        appendLabel(label);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitLabel(label);

-        }

-    }

-

-    public void visitLdcInsn(final Object cst) {

-        buf.setLength(0);

-        buf.append(tab2).append("LDC ");

-        if (cst instanceof String) {

-            AbstractVisitor.appendString(buf, (String) cst);

-        } else if (cst instanceof Type) {

-            buf.append(((Type) cst).getDescriptor()).append(".class");

-        } else {

-            buf.append(cst);

-        }

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitLdcInsn(cst);

-        }

-    }

-

-    public void visitIincInsn(final int var, final int increment) {

-        buf.setLength(0);

-        buf.append(tab2)

-                .append("IINC ")

-                .append(var)

-                .append(' ')

-                .append(increment)

-                .append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitIincInsn(var, increment);

-        }

-    }

-

-    public void visitTableSwitchInsn(

-        final int min,

-        final int max,

-        final Label dflt,

-        final Label[] labels)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append("TABLESWITCH\n");

-        for (int i = 0; i < labels.length; ++i) {

-            buf.append(tab3).append(min + i).append(": ");

-            appendLabel(labels[i]);

-            buf.append('\n');

-        }

-        buf.append(tab3).append("default: ");

-        appendLabel(dflt);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitTableSwitchInsn(min, max, dflt, labels);

-        }

-    }

-

-    public void visitLookupSwitchInsn(

-        final Label dflt,

-        final int[] keys,

-        final Label[] labels)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append("LOOKUPSWITCH\n");

-        for (int i = 0; i < labels.length; ++i) {

-            buf.append(tab3).append(keys[i]).append(": ");

-            appendLabel(labels[i]);

-            buf.append('\n');

-        }

-        buf.append(tab3).append("default: ");

-        appendLabel(dflt);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitLookupSwitchInsn(dflt, keys, labels);

-        }

-    }

-

-    public void visitMultiANewArrayInsn(final String desc, final int dims) {

-        buf.setLength(0);

-        buf.append(tab2).append("MULTIANEWARRAY ");

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append(' ').append(dims).append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitMultiANewArrayInsn(desc, dims);

-        }

-    }

-

-    public void visitTryCatchBlock(

-        final Label start,

-        final Label end,

-        final Label handler,

-        final String type)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append("TRYCATCHBLOCK ");

-        appendLabel(start);

-        buf.append(' ');

-        appendLabel(end);

-        buf.append(' ');

-        appendLabel(handler);

-        buf.append(' ');

-        appendDescriptor(INTERNAL_NAME, type);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitTryCatchBlock(start, end, handler, type);

-        }

-    }

-

-    public void visitLocalVariable(

-        final String name,

-        final String desc,

-        final String signature,

-        final Label start,

-        final Label end,

-        final int index)

-    {

-        buf.setLength(0);

-        buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');

-        appendDescriptor(FIELD_DESCRIPTOR, desc);

-        buf.append(' ');

-        appendLabel(start);

-        buf.append(' ');

-        appendLabel(end);

-        buf.append(' ').append(index).append('\n');

-

-        if (signature != null) {

-            buf.append(tab2);

-            appendDescriptor(FIELD_SIGNATURE, signature);

-

-            TraceSignatureVisitor sv = new TraceSignatureVisitor(0);

-            SignatureReader r = new SignatureReader(signature);

-            r.acceptType(sv);

-            buf.append(tab2)

-                    .append("// declaration: ")

-                    .append(sv.getDeclaration())

-                    .append('\n');

-        }

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitLocalVariable(name, desc, signature, start, end, index);

-        }

-    }

-

-    public void visitLineNumber(final int line, final Label start) {

-        buf.setLength(0);

-        buf.append(tab2).append("LINENUMBER ").append(line).append(' ');

-        appendLabel(start);

-        buf.append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitLineNumber(line, start);

-        }

-    }

-

-    public void visitMaxs(final int maxStack, final int maxLocals) {

-        buf.setLength(0);

-        buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n');

-        text.add(buf.toString());

-

-        buf.setLength(0);

-        buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n');

-        text.add(buf.toString());

-

-        if (mv != null) {

-            mv.visitMaxs(maxStack, maxLocals);

-        }

-    }

-

-    public void visitEnd() {

-        super.visitEnd();

-

-        if (mv != null) {

-            mv.visitEnd();

-        }

-    }

-

-    // ------------------------------------------------------------------------

-    // Utility methods

-    // ------------------------------------------------------------------------

-

-    private void appendFrameTypes(final int n, final Object[] o) {

-        for (int i = 0; i < n; ++i) {

-            if (i > 0) {

-                buf.append(' ');

-            }

-            if (o[i] instanceof String) {

-                String desc = (String) o[i];

-                if (desc.startsWith("[")) {

-                    appendDescriptor(FIELD_DESCRIPTOR, desc);

-                } else {

-                    appendDescriptor(INTERNAL_NAME, desc);

-                }

-            } else if (o[i] instanceof Integer) {

-                switch (((Integer) o[i]).intValue()) {

-                    case 0:

-                        appendDescriptor(FIELD_DESCRIPTOR, "T");

-                        break;

-                    case 1:

-                        appendDescriptor(FIELD_DESCRIPTOR, "I");

-                        break;

-                    case 2:

-                        appendDescriptor(FIELD_DESCRIPTOR, "F");

-                        break;

-                    case 3:

-                        appendDescriptor(FIELD_DESCRIPTOR, "D");

-                        break;

-                    case 4:

-                        appendDescriptor(FIELD_DESCRIPTOR, "J");

-                        break;

-                    case 5:

-                        appendDescriptor(FIELD_DESCRIPTOR, "N");

-                        break;

-                    case 6:

-                        appendDescriptor(FIELD_DESCRIPTOR, "U");

-                        break;

-                }

-            } else {

-                appendLabel((Label) o[i]);

-            }

-        }

-    }

-

-    /**

-     * Appends the name of the given label to {@link #buf buf}. Creates a new

-     * label name if the given label does not yet have one.

-     * 

-     * @param l a label.

-     */

-    protected void appendLabel(final Label l) {

-        String name = (String) labelNames.get(l);

-        if (name == null) {

-            name = "L" + labelNames.size();

-            labelNames.put(l, name);

-        }

-        buf.append(name);

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/TraceSignatureVisitor.java b/cglib-and-asm/src/org/mockito/asm/util/TraceSignatureVisitor.java
deleted file mode 100644
index 4006a51..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/TraceSignatureVisitor.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/***

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import org.mockito.asm.Opcodes;

-import org.mockito.asm.signature.SignatureVisitor;

-

-/**

- * A {@link SignatureVisitor} that prints a disassembled view of the signature

- * it visits.

- * 

- * @author Eugene Kuleshov

- * @author Eric Bruneton

- */

-public class TraceSignatureVisitor implements SignatureVisitor {

-

-    private final StringBuffer declaration;

-

-    private boolean isInterface;

-

-    private boolean seenFormalParameter;

-

-    private boolean seenInterfaceBound;

-

-    private boolean seenParameter;

-

-    private boolean seenInterface;

-

-    private StringBuffer returnType;

-

-    private StringBuffer exceptions;

-

-    /**

-     * Stack used to keep track of class types that have arguments. Each element

-     * of this stack is a boolean encoded in one bit. The top of the stack is

-     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =

-     * /2.

-     */

-    private int argumentStack;

-

-    /**

-     * Stack used to keep track of array class types. Each element of this stack

-     * is a boolean encoded in one bit. The top of the stack is the lowest order

-     * bit. Pushing false = *2, pushing true = *2+1, popping = /2.

-     */

-    private int arrayStack;

-

-    private String separator = "";

-

-    public TraceSignatureVisitor(final int access) {

-        isInterface = (access & Opcodes.ACC_INTERFACE) != 0;

-        this.declaration = new StringBuffer();

-    }

-

-    private TraceSignatureVisitor(final StringBuffer buf) {

-        this.declaration = buf;

-    }

-

-    public void visitFormalTypeParameter(final String name) {

-        declaration.append(seenFormalParameter ? ", " : "<").append(name);

-        seenFormalParameter = true;

-        seenInterfaceBound = false;

-    }

-

-    public SignatureVisitor visitClassBound() {

-        separator = " extends ";

-        startType();

-        return this;

-    }

-

-    public SignatureVisitor visitInterfaceBound() {

-        separator = seenInterfaceBound ? ", " : " extends ";

-        seenInterfaceBound = true;

-        startType();

-        return this;

-    }

-

-    public SignatureVisitor visitSuperclass() {

-        endFormals();

-        separator = " extends ";

-        startType();

-        return this;

-    }

-

-    public SignatureVisitor visitInterface() {

-        separator = seenInterface ? ", " : isInterface

-                ? " extends "

-                : " implements ";

-        seenInterface = true;

-        startType();

-        return this;

-    }

-

-    public SignatureVisitor visitParameterType() {

-        endFormals();

-        if (seenParameter) {

-            declaration.append(", ");

-        } else {

-            seenParameter = true;

-            declaration.append('(');

-        }

-        startType();

-        return this;

-    }

-

-    public SignatureVisitor visitReturnType() {

-        endFormals();

-        if (seenParameter) {

-            seenParameter = false;

-        } else {

-            declaration.append('(');

-        }

-        declaration.append(')');

-        returnType = new StringBuffer();

-        return new TraceSignatureVisitor(returnType);

-    }

-

-    public SignatureVisitor visitExceptionType() {

-        if (exceptions == null) {

-            exceptions = new StringBuffer();

-        } else {

-            exceptions.append(", ");

-        }

-        // startType();

-        return new TraceSignatureVisitor(exceptions);

-    }

-

-    public void visitBaseType(final char descriptor) {

-        switch (descriptor) {

-            case 'V':

-                declaration.append("void");

-                break;

-            case 'B':

-                declaration.append("byte");

-                break;

-            case 'J':

-                declaration.append("long");

-                break;

-            case 'Z':

-                declaration.append("boolean");

-                break;

-            case 'I':

-                declaration.append("int");

-                break;

-            case 'S':

-                declaration.append("short");

-                break;

-            case 'C':

-                declaration.append("char");

-                break;

-            case 'F':

-                declaration.append("float");

-                break;

-            // case 'D':

-            default:

-                declaration.append("double");

-                break;

-        }

-        endType();

-    }

-

-    public void visitTypeVariable(final String name) {

-        declaration.append(name);

-        endType();

-    }

-

-    public SignatureVisitor visitArrayType() {

-        startType();

-        arrayStack |= 1;

-        return this;

-    }

-

-    public void visitClassType(final String name) {

-        if ("java/lang/Object".equals(name)) {

-            // Map<java.lang.Object,java.util.List>

-            // or

-            // abstract public V get(Object key); (seen in Dictionary.class)

-            // should have Object

-            // but java.lang.String extends java.lang.Object is unnecessary

-            boolean needObjectClass = argumentStack % 2 != 0 || seenParameter;

-            if (needObjectClass) {

-                declaration.append(separator).append(name.replace('/', '.'));

-            }

-        } else {

-            declaration.append(separator).append(name.replace('/', '.'));

-        }

-        separator = "";

-        argumentStack *= 2;

-    }

-

-    public void visitInnerClassType(final String name) {

-        if (argumentStack % 2 != 0) {

-            declaration.append('>');

-        }

-        argumentStack /= 2;

-        declaration.append('.');

-        declaration.append(separator).append(name.replace('/', '.'));

-        separator = "";

-        argumentStack *= 2;

-    }

-

-    public void visitTypeArgument() {

-        if (argumentStack % 2 == 0) {

-            ++argumentStack;

-            declaration.append('<');

-        } else {

-            declaration.append(", ");

-        }

-        declaration.append('?');

-    }

-

-    public SignatureVisitor visitTypeArgument(final char tag) {

-        if (argumentStack % 2 == 0) {

-            ++argumentStack;

-            declaration.append('<');

-        } else {

-            declaration.append(", ");

-        }

-

-        if (tag == EXTENDS) {

-            declaration.append("? extends ");

-        } else if (tag == SUPER) {

-            declaration.append("? super ");

-        }

-

-        startType();

-        return this;

-    }

-

-    public void visitEnd() {

-        if (argumentStack % 2 != 0) {

-            declaration.append('>');

-        }

-        argumentStack /= 2;

-        endType();

-    }

-

-    public String getDeclaration() {

-        return declaration.toString();

-    }

-

-    public String getReturnType() {

-        return returnType == null ? null : returnType.toString();

-    }

-

-    public String getExceptions() {

-        return exceptions == null ? null : exceptions.toString();

-    }

-

-    // -----------------------------------------------

-

-    private void endFormals() {

-        if (seenFormalParameter) {

-            declaration.append('>');

-            seenFormalParameter = false;

-        }

-    }

-

-    private void startType() {

-        arrayStack *= 2;

-    }

-

-    private void endType() {

-        if (arrayStack % 2 == 0) {

-            arrayStack /= 2;

-        } else {

-            while (arrayStack % 2 != 0) {

-                arrayStack /= 2;

-                declaration.append("[]");

-            }

-        }

-    }

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/Traceable.java b/cglib-and-asm/src/org/mockito/asm/util/Traceable.java
deleted file mode 100644
index 8a73467..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/Traceable.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2007 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

- */

-package org.mockito.asm.util;

-

-import java.util.Map;

-

-/**

- * An attribute that can print eadable representation of the attribute.

- * 

- * Implementation should construct readable output from an attribute data

- * structures for current attribute state. Such representation could be used in

- * unit test assertions.

- * 

- * @author Eugene Kuleshov

- */

-public interface Traceable {

-

-    /**

-     * Build a human readable representation of the attribute.

-     * 

-     * @param buf A buffer used for printing Java code.

-     * @param labelNames map of label instances to their names.

-     */

-    void trace(StringBuffer buf, Map labelNames);

-}

diff --git a/cglib-and-asm/src/org/mockito/asm/util/package.html b/cglib-and-asm/src/org/mockito/asm/util/package.html
deleted file mode 100644
index ce91531..0000000
--- a/cglib-and-asm/src/org/mockito/asm/util/package.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<html>

-<!--

- * ASM: a very small and fast Java bytecode manipulation framework

- * Copyright (c) 2000-2005 INRIA, France Telecom

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- * 1. Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- * 2. Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in the

- *    documentation and/or other materials provided with the distribution.

- * 3. Neither the name of the copyright holders nor the names of its

- *    contributors may be used to endorse or promote products derived from

- *    this software without specific prior written permission.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

- * THE POSSIBILITY OF SUCH DAMAGE.

--->

-<body>

-Provides ASM visitors that can be useful for programming and

-debugging purposes. These class visitors are normally not used by applications

-at runtime. This is why they are bundled in an optional <tt>asm-util.jar</tt>

-library that is separated from (but requires) the <tt>asm.jar</tt> library,

-which contains the core ASM framework.

-

-@since ASM 1.3.2

-</body>

-</html>

diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BeanCopier.java b/cglib-and-asm/src/org/mockito/cglib/beans/BeanCopier.java
deleted file mode 100644
index 14fe383..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BeanCopier.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-import java.util.*;
-
-/**
- * @author Chris Nokleberg
- */
-abstract public class BeanCopier
-{
-    private static final BeanCopierKey KEY_FACTORY =
-      (BeanCopierKey)KeyFactory.create(BeanCopierKey.class);
-    private static final Type CONVERTER =
-      TypeUtils.parseType("org.mockito.cglib.core.Converter");
-    private static final Type BEAN_COPIER =
-      TypeUtils.parseType("org.mockito.cglib.beans.BeanCopier");
-    private static final Signature COPY =
-      new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER });
-    private static final Signature CONVERT =
-      TypeUtils.parseSignature("Object convert(Object, Class, Object)");
-    
-    interface BeanCopierKey {
-        public Object newInstance(String source, String target, boolean useConverter);
-    }
-
-    public static BeanCopier create(Class source, Class target, boolean useConverter) {
-        Generator gen = new Generator();
-        gen.setSource(source);
-        gen.setTarget(target);
-        gen.setUseConverter(useConverter);
-        return gen.create();
-    }
-
-    abstract public void copy(Object from, Object to, Converter converter);
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(BeanCopier.class.getName());
-        private Class source;
-        private Class target;
-        private boolean useConverter;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        public void setSource(Class source) {
-            if(!Modifier.isPublic(source.getModifiers())){ 
-               setNamePrefix(source.getName());
-            }
-            this.source = source;
-        }
-        
-        public void setTarget(Class target) {
-            if(!Modifier.isPublic(target.getModifiers())){ 
-               setNamePrefix(target.getName());
-            }
-          
-            this.target = target;
-        }
-
-        public void setUseConverter(boolean useConverter) {
-            this.useConverter = useConverter;
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return source.getClassLoader();
-        }
-
-        public BeanCopier create() {
-            Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter);
-            return (BeanCopier)super.create(key);
-        }
-
-        public void generateClass(ClassVisitor v) {
-            Type sourceType = Type.getType(source);
-            Type targetType = Type.getType(target);
-            ClassEmitter ce = new ClassEmitter(v);
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           BEAN_COPIER,
-                           null,
-                           Constants.SOURCE_FILE);
-
-            EmitUtils.null_constructor(ce);
-            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null);
-            PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source);
-            PropertyDescriptor[] setters = ReflectUtils.getBeanGetters(target);
-
-            Map names = new HashMap();
-            for (int i = 0; i < getters.length; i++) {
-                names.put(getters[i].getName(), getters[i]);
-            }
-            Local targetLocal = e.make_local();
-            Local sourceLocal = e.make_local();
-            if (useConverter) {
-                e.load_arg(1);
-                e.checkcast(targetType);
-                e.store_local(targetLocal);
-                e.load_arg(0);                
-                e.checkcast(sourceType);
-                e.store_local(sourceLocal);
-            } else {
-                e.load_arg(1);
-                e.checkcast(targetType);
-                e.load_arg(0);
-                e.checkcast(sourceType);
-            }
-            for (int i = 0; i < setters.length; i++) {
-                PropertyDescriptor setter = setters[i];
-                PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName());
-                if (getter != null) {
-                    MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod());
-                    MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod());
-                    if (useConverter) {
-                        Type setterType = write.getSignature().getArgumentTypes()[0];
-                        e.load_local(targetLocal);
-                        e.load_arg(2);
-                        e.load_local(sourceLocal);
-                        e.invoke(read);
-                        e.box(read.getSignature().getReturnType());
-                        EmitUtils.load_class(e, setterType);
-                        e.push(write.getSignature().getName());
-                        e.invoke_interface(CONVERTER, CONVERT);
-                        e.unbox_or_zero(setterType);
-                        e.invoke(write);
-                    } else if (compatible(getter, setter)) {
-                        e.dup2();
-                        e.invoke(read);
-                        e.invoke(write);
-                    }
-                }
-            }
-            e.return_value();
-            e.end_method();
-            ce.end_class();
-        }
-
-        private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) {
-            // TODO: allow automatic widening conversions?
-            return setter.getPropertyType().isAssignableFrom(getter.getPropertyType());
-        }
-
-        protected Object firstInstance(Class type) {
-            return ReflectUtils.newInstance(type);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return instance;
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BeanGenerator.java b/cglib-and-asm/src/org/mockito/cglib/beans/BeanGenerator.java
deleted file mode 100644
index 63c3ddd..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BeanGenerator.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.beans.PropertyDescriptor;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * @author Juozas Baliuka, Chris Nokleberg
- */
-public class BeanGenerator extends AbstractClassGenerator
-{
-    private static final Source SOURCE = new Source(BeanGenerator.class.getName());
-    private static final BeanGeneratorKey KEY_FACTORY =
-      (BeanGeneratorKey)KeyFactory.create(BeanGeneratorKey.class);
-    
-    interface BeanGeneratorKey {
-        public Object newInstance(String superclass, Map props);
-    }
-
-    private Class superclass;
-    private Map props = new HashMap();
-    private boolean classOnly;
-
-    public BeanGenerator() {
-        super(SOURCE);
-    }
-
-    /**
-     * Set the class which the generated class will extend. The class
-     * must not be declared as final, and must have a non-private
-     * no-argument constructor.
-     * @param superclass class to extend, or null to extend Object
-     */
-    public void setSuperclass(Class superclass) {
-        if (superclass != null && superclass.equals(Object.class)) {
-            superclass = null;
-        }
-        this.superclass = superclass;
-    }
-
-    public void addProperty(String name, Class type) {
-        if (props.containsKey(name)) {
-            throw new IllegalArgumentException("Duplicate property name \"" + name + "\"");
-        }
-        props.put(name, Type.getType(type));
-    }
-
-    protected ClassLoader getDefaultClassLoader() {
-        if (superclass != null) {
-            return superclass.getClassLoader();
-        } else {
-            return null;
-        }
-    }
-
-    public Object create() {
-        classOnly = false;
-        return createHelper();
-    }
-
-    public Object createClass() {
-        classOnly = true;
-        return createHelper();
-    }
-
-    private Object createHelper() {
-        if (superclass != null) {
-            setNamePrefix(superclass.getName());
-        }
-        String superName = (superclass != null) ? superclass.getName() : "java.lang.Object";
-        Object key = KEY_FACTORY.newInstance(superName, props);
-        return super.create(key);
-    }
-
-    public void generateClass(ClassVisitor v) throws Exception {
-        int size = props.size();
-        String[] names = (String[])props.keySet().toArray(new String[size]);
-        Type[] types = new Type[size];
-        for (int i = 0; i < size; i++) {
-            types[i] = (Type)props.get(names[i]);
-        }
-        ClassEmitter ce = new ClassEmitter(v);
-        ce.begin_class(Constants.V1_2,
-                       Constants.ACC_PUBLIC,
-                       getClassName(),
-                       superclass != null ? Type.getType(superclass) : Constants.TYPE_OBJECT,
-                       null,
-                       null);
-        EmitUtils.null_constructor(ce);
-        EmitUtils.add_properties(ce, names, types);
-        ce.end_class();
-    }
-
-    protected Object firstInstance(Class type) {
-        if (classOnly) {
-            return type;
-        } else {
-            return ReflectUtils.newInstance(type);
-        }
-    }
-
-    protected Object nextInstance(Object instance) {
-        Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass();
-        if (classOnly) {
-            return protoclass;
-        } else {
-            return ReflectUtils.newInstance(protoclass);
-        }
-    }
-
-    public static void addProperties(BeanGenerator gen, Map props) {
-        for (Iterator it = props.keySet().iterator(); it.hasNext();) {
-            String name = (String)it.next();
-            gen.addProperty(name, (Class)props.get(name));
-        }
-    }
-
-    public static void addProperties(BeanGenerator gen, Class type) {
-        addProperties(gen, ReflectUtils.getBeanProperties(type));
-    }
-
-    public static void addProperties(BeanGenerator gen, PropertyDescriptor[] descriptors) {
-        for (int i = 0; i < descriptors.length; i++) {
-            gen.addProperty(descriptors[i].getName(), descriptors[i].getPropertyType());
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BeanMap.java b/cglib-and-asm/src/org/mockito/cglib/beans/BeanMap.java
deleted file mode 100644
index 78d06f8..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BeanMap.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.beans.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.*;
-
-/**
- * A <code>Map</code>-based view of a JavaBean.  The default set of keys is the
- * union of all property names (getters or setters). An attempt to set
- * a read-only property will be ignored, and write-only properties will
- * be returned as <code>null</code>. Removal of objects is not a
- * supported (the key set is fixed).
- * @author Chris Nokleberg
- */
-abstract public class BeanMap implements Map {
-    /**
-     * Limit the properties reflected in the key set of the map
-     * to readable properties.
-     * @see BeanMap.Generator#setRequire
-     */
-    public static final int REQUIRE_GETTER = 1;
-
-    /**
-     * Limit the properties reflected in the key set of the map
-     * to writable properties.
-     * @see BeanMap.Generator#setRequire
-     */
-    public static final int REQUIRE_SETTER = 2;
-    
-    /**
-     * Helper method to create a new <code>BeanMap</code>.  For finer
-     * control over the generated instance, use a new instance of
-     * <code>BeanMap.Generator</code> instead of this static method.
-     * @param bean the JavaBean underlying the map
-     * @return a new <code>BeanMap</code> instance
-     */
-    public static BeanMap create(Object bean) {
-        Generator gen = new Generator();
-        gen.setBean(bean);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(BeanMap.class.getName());
-
-        private static final BeanMapKey KEY_FACTORY =
-          (BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME);
-
-        interface BeanMapKey {
-            public Object newInstance(Class type, int require);
-        }
-        
-        private Object bean;
-        private Class beanClass;
-        private int require;
-        
-        public Generator() {
-            super(SOURCE);
-        }
-
-        /**
-         * Set the bean that the generated map should reflect. The bean may be swapped
-         * out for another bean of the same type using {@link #setBean}.
-         * Calling this method overrides any value previously set using {@link #setBeanClass}.
-         * You must call either this method or {@link #setBeanClass} before {@link #create}.
-         * @param bean the initial bean
-         */
-        public void setBean(Object bean) {
-            this.bean = bean;
-            if (bean != null)
-                beanClass = bean.getClass();
-        }
-
-        /**
-         * Set the class of the bean that the generated map should support.
-         * You must call either this method or {@link #setBeanClass} before {@link #create}.
-         * @param beanClass the class of the bean
-         */
-        public void setBeanClass(Class beanClass) {
-            this.beanClass = beanClass;
-        }
-
-        /**
-         * Limit the properties reflected by the generated map.
-         * @param require any combination of {@link #REQUIRE_GETTER} and
-         * {@link #REQUIRE_SETTER}; default is zero (any property allowed)
-         */
-        public void setRequire(int require) {
-            this.require = require;
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return beanClass.getClassLoader();
-        }
-
-        /**
-         * Create a new instance of the <code>BeanMap</code>. An existing
-         * generated class will be reused if possible.
-         */
-        public BeanMap create() {
-            if (beanClass == null)
-                throw new IllegalArgumentException("Class of bean unknown");
-            setNamePrefix(beanClass.getName());
-            return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require));
-        }
-
-        public void generateClass(ClassVisitor v) throws Exception {
-            new BeanMapEmitter(v, getClassName(), beanClass, require);
-        }
-
-        protected Object firstInstance(Class type) {
-            return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return ((BeanMap)instance).newInstance(bean);
-        }
-    }
-
-    /**
-     * Create a new <code>BeanMap</code> instance using the specified bean.
-     * This is faster than using the {@link #create} static method.
-     * @param bean the JavaBean underlying the map
-     * @return a new <code>BeanMap</code> instance
-     */
-    abstract public BeanMap newInstance(Object bean);
-
-    /**
-     * Get the type of a property.
-     * @param name the name of the JavaBean property
-     * @return the type of the property, or null if the property does not exist
-     */
-    abstract public Class getPropertyType(String name);
-
-    protected Object bean;
-
-    protected BeanMap() {
-    }
-
-    protected BeanMap(Object bean) {
-        setBean(bean);
-    }
-
-    public Object get(Object key) {
-        return get(bean, key);
-    }
-
-    public Object put(Object key, Object value) {
-        return put(bean, key, value);
-    }
-
-    /**
-     * Get the property of a bean. This allows a <code>BeanMap</code>
-     * to be used statically for multiple beans--the bean instance tied to the
-     * map is ignored and the bean passed to this method is used instead.
-     * @param bean the bean to query; must be compatible with the type of
-     * this <code>BeanMap</code>
-     * @param key must be a String
-     * @return the current value, or null if there is no matching property
-     */
-    abstract public Object get(Object bean, Object key);
-
-    /**
-     * Set the property of a bean. This allows a <code>BeanMap</code>
-     * to be used statically for multiple beans--the bean instance tied to the
-     * map is ignored and the bean passed to this method is used instead.
-     * @param key must be a String
-     * @return the old value, if there was one, or null
-     */
-    abstract public Object put(Object bean, Object key, Object value);
-
-    /**
-     * Change the underlying bean this map should use.
-     * @param bean the new JavaBean
-     * @see #getBean
-     */
-    public void setBean(Object bean) {
-        this.bean = bean;
-    }
-
-    /**
-     * Return the bean currently in use by this map.
-     * @return the current JavaBean
-     * @see #setBean
-     */
-    public Object getBean() {
-        return bean;
-    }
-
-    public void clear() {
-        throw new UnsupportedOperationException();
-    }
-
-    public boolean containsKey(Object key) {
-        return keySet().contains(key);
-    }
-
-    public boolean containsValue(Object value) {
-        for (Iterator it = keySet().iterator(); it.hasNext();) {
-            Object v = get(it.next());
-            if (((value == null) && (v == null)) || value.equals(v))
-                return true;
-        }
-        return false;
-    }
-
-    public int size() {
-        return keySet().size();
-    }
-
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    public Object remove(Object key) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void putAll(Map t) {
-        for (Iterator it = t.keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
-            put(key, t.get(key));
-        }
-    }
-
-    public boolean equals(Object o) {
-        if (o == null || !(o instanceof Map)) {
-            return false;
-        }
-        Map other = (Map)o;
-        if (size() != other.size()) {
-            return false;
-        }
-        for (Iterator it = keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
-            if (!other.containsKey(key)) {
-                return false;
-            }
-            Object v1 = get(key);
-            Object v2 = other.get(key);
-            if (!((v1 == null) ? v2 == null : v1.equals(v2))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public int hashCode() {
-        int code = 0;
-        for (Iterator it = keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
-            Object value = get(key);
-            code += ((key == null) ? 0 : key.hashCode()) ^
-                ((value == null) ? 0 : value.hashCode());
-        }
-        return code;
-    }
-
-    // TODO: optimize
-    public Set entrySet() {
-        HashMap copy = new HashMap();
-        for (Iterator it = keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
-            copy.put(key, get(key));
-        }
-        return Collections.unmodifiableMap(copy).entrySet();
-    }
-
-    public Collection values() {
-        Set keys = keySet();
-        List values = new ArrayList(keys.size());
-        for (Iterator it = keys.iterator(); it.hasNext();) {
-            values.add(get(it.next()));
-        }
-        return Collections.unmodifiableCollection(values);
-    }
-
-    /*
-     * @see java.util.AbstractMap#toString
-     */
-    public String toString()
-    {
-        StringBuffer sb = new StringBuffer();
-        sb.append('{');
-        for (Iterator it = keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
-            sb.append(key);
-            sb.append('=');
-            sb.append(get(key));
-            if (it.hasNext()) {
-                sb.append(", ");
-            }
-        }
-        sb.append('}');
-        return sb.toString();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BeanMapEmitter.java b/cglib-and-asm/src/org/mockito/cglib/beans/BeanMapEmitter.java
deleted file mode 100644
index 4ced61c..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BeanMapEmitter.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.beans.*;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class BeanMapEmitter extends ClassEmitter {
-    private static final Type BEAN_MAP =
-      TypeUtils.parseType("org.mockito.cglib.beans.BeanMap");
-    private static final Type FIXED_KEY_SET =
-      TypeUtils.parseType("org.mockito.cglib.beans.FixedKeySet");
-    private static final Signature CSTRUCT_OBJECT =
-      TypeUtils.parseConstructor("Object");
-    private static final Signature CSTRUCT_STRING_ARRAY =
-      TypeUtils.parseConstructor("String[]");
-    private static final Signature BEAN_MAP_GET =
-      TypeUtils.parseSignature("Object get(Object, Object)");
-    private static final Signature BEAN_MAP_PUT =
-      TypeUtils.parseSignature("Object put(Object, Object, Object)");
-    private static final Signature KEY_SET =
-      TypeUtils.parseSignature("java.util.Set keySet()");
-    private static final Signature NEW_INSTANCE =
-      new Signature("newInstance", BEAN_MAP, new Type[]{ Constants.TYPE_OBJECT });
-    private static final Signature GET_PROPERTY_TYPE =
-      TypeUtils.parseSignature("Class getPropertyType(String)");
-
-    public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) {
-        super(v);
-
-        begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE);
-        EmitUtils.null_constructor(this);
-        EmitUtils.factory_method(this, NEW_INSTANCE);
-        generateConstructor();
-            
-        Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type));
-        Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type));
-        Map allProps = new HashMap();
-        allProps.putAll(getters);
-        allProps.putAll(setters);
-
-        if (require != 0) {
-            for (Iterator it = allProps.keySet().iterator(); it.hasNext();) {
-                String name = (String)it.next();
-                if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) ||
-                    (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) {
-                    it.remove();
-                    getters.remove(name);
-                    setters.remove(name);
-                }
-            }
-        }
-        generateGet(type, getters);
-        generatePut(type, setters);
-
-        String[] allNames = getNames(allProps);
-        generateKeySet(allNames);
-        generateGetPropertyType(allProps, allNames);
-        end_class();
-    }
-
-    private Map makePropertyMap(PropertyDescriptor[] props) {
-        Map names = new HashMap();
-        for (int i = 0; i < props.length; i++) {
-            names.put(((PropertyDescriptor)props[i]).getName(), props[i]);
-        }
-        return names;
-    }
-
-    private String[] getNames(Map propertyMap) {
-        return (String[])propertyMap.keySet().toArray(new String[propertyMap.size()]);
-    }
-
-    private void generateConstructor() {
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
-        e.load_this();
-        e.load_arg(0);
-        e.super_invoke_constructor(CSTRUCT_OBJECT);
-        e.return_value();
-        e.end_method();
-    }
-        
-    private void generateGet(Class type, final Map getters) {
-        final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null);
-        e.load_arg(0);
-        e.checkcast(Type.getType(type));
-        e.load_arg(1);
-        e.checkcast(Constants.TYPE_STRING);
-        EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                PropertyDescriptor pd = (PropertyDescriptor)getters.get(key);
-                MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod());
-                e.invoke(method);
-                e.box(method.getSignature().getReturnType());
-                e.return_value();
-            }
-            public void processDefault() {
-                e.aconst_null();
-                e.return_value();
-            }
-        });
-        e.end_method();
-    }
-
-    private void generatePut(Class type, final Map setters) {
-        final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null);
-        e.load_arg(0);
-        e.checkcast(Type.getType(type));
-        e.load_arg(1);
-        e.checkcast(Constants.TYPE_STRING);
-        EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                PropertyDescriptor pd = (PropertyDescriptor)setters.get(key);
-                if (pd.getReadMethod() == null) {
-                    e.aconst_null();
-                } else {
-                    MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod());
-                    e.dup();
-                    e.invoke(read);
-                    e.box(read.getSignature().getReturnType());
-                }
-                e.swap(); // move old value behind bean
-                e.load_arg(2); // new value
-                MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod());
-                e.unbox(write.getSignature().getArgumentTypes()[0]);
-                e.invoke(write);
-                e.return_value();
-            }
-            public void processDefault() {
-                // fall-through
-            }
-        });
-        e.aconst_null();
-        e.return_value();
-        e.end_method();
-    }
-            
-    private void generateKeySet(String[] allNames) {
-        // static initializer
-        declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null);
-
-        CodeEmitter e = begin_static();
-        e.new_instance(FIXED_KEY_SET);
-        e.dup();
-        EmitUtils.push_array(e, allNames);
-        e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY);
-        e.putfield("keys");
-        e.return_value();
-        e.end_method();
-
-        // keySet
-        e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null);
-        e.load_this();
-        e.getfield("keys");
-        e.return_value();
-        e.end_method();
-    }
-
-    private void generateGetPropertyType(final Map allProps, String[] allNames) {
-        final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null);
-        e.load_arg(0);
-        EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key);
-                EmitUtils.load_class(e, Type.getType(pd.getPropertyType()));
-                e.return_value();
-            }
-            public void processDefault() {
-                e.aconst_null();
-                e.return_value();
-            }
-        });
-        e.end_method();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BulkBean.java b/cglib-and-asm/src/org/mockito/cglib/beans/BulkBean.java
deleted file mode 100644
index f8d053c..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BulkBean.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.*;
-
-/**
- * @author Juozas Baliuka
- */
-abstract public class BulkBean
-{
-    private static final BulkBeanKey KEY_FACTORY =
-      (BulkBeanKey)KeyFactory.create(BulkBeanKey.class);
-    
-    interface BulkBeanKey {
-        public Object newInstance(String target, String[] getters, String[] setters, String[] types);
-    }
-    
-    protected Class target;
-    protected String[] getters, setters;
-    protected Class[] types;
-    
-    protected BulkBean() { }
-    
-    abstract public void getPropertyValues(Object bean, Object[] values);
-    abstract public void setPropertyValues(Object bean, Object[] values);
-
-    public Object[] getPropertyValues(Object bean) {
-        Object[] values = new Object[getters.length];
-        getPropertyValues(bean, values);
-        return values;
-    }
-    
-    public Class[] getPropertyTypes() {
-        return (Class[])types.clone();
-    }
-    
-    public String[] getGetters() {
-        return (String[])getters.clone();
-    }
-    
-    public String[] getSetters() {
-        return (String[])setters.clone();
-    }
-
-    public static BulkBean create(Class target, String[] getters, String[] setters, Class[] types) {
-        Generator gen = new Generator();
-        gen.setTarget(target);
-        gen.setGetters(getters);
-        gen.setSetters(setters);
-        gen.setTypes(types);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(BulkBean.class.getName());
-        private Class target;
-        private String[] getters;
-        private String[] setters;
-        private Class[] types;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        public void setTarget(Class target) {
-            this.target = target;
-        }
-
-        public void setGetters(String[] getters) {
-            this.getters = getters;
-        }
-
-        public void setSetters(String[] setters) {
-            this.setters = setters;
-        }
-
-        public void setTypes(Class[] types) {
-            this.types = types;
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return target.getClassLoader();
-        }
-
-        public BulkBean create() {
-            setNamePrefix(target.getName());
-            String targetClassName = target.getName();
-            String[] typeClassNames = ReflectUtils.getNames(types);
-            Object key = KEY_FACTORY.newInstance(targetClassName, getters, setters, typeClassNames);
-            return (BulkBean)super.create(key);
-        }
-
-        public void generateClass(ClassVisitor v) throws Exception {
-            new BulkBeanEmitter(v, getClassName(), target, getters, setters, types);
-        }
-
-        protected Object firstInstance(Class type) {
-            BulkBean instance = (BulkBean)ReflectUtils.newInstance(type);
-            instance.target = target;
-                    
-            int length = getters.length;
-            instance.getters = new String[length];
-            System.arraycopy(getters, 0, instance.getters, 0, length);
-                    
-            instance.setters = new String[length];
-            System.arraycopy(setters, 0, instance.setters, 0, length);
-                    
-            instance.types = new Class[types.length];
-            System.arraycopy(types, 0, instance.types, 0, types.length);
-
-            return instance;
-        }
-
-        protected Object nextInstance(Object instance) {
-            return instance;
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BulkBeanEmitter.java b/cglib-and-asm/src/org/mockito/cglib/beans/BulkBeanEmitter.java
deleted file mode 100644
index 06f0873..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BulkBeanEmitter.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-    
-class BulkBeanEmitter extends ClassEmitter {
-    private static final Signature GET_PROPERTY_VALUES =
-      TypeUtils.parseSignature("void getPropertyValues(Object, Object[])");
-    private static final Signature SET_PROPERTY_VALUES =
-      TypeUtils.parseSignature("void setPropertyValues(Object, Object[])");
-    private static final Signature CSTRUCT_EXCEPTION =
-      TypeUtils.parseConstructor("Throwable, int");
-    private static final Type BULK_BEAN =
-      TypeUtils.parseType("org.mockito.cglib.beans.BulkBean");
-    private static final Type BULK_BEAN_EXCEPTION =
-      TypeUtils.parseType("org.mockito.cglib.beans.BulkBeanException");
-        
-    public BulkBeanEmitter(ClassVisitor v,
-                           String className,
-                           Class target,
-                           String[] getterNames,
-                           String[] setterNames,
-                           Class[] types) {
-        super(v);
-
-        Method[] getters = new Method[getterNames.length];
-        Method[] setters = new Method[setterNames.length];
-        validate(target, getterNames, setterNames, types, getters, setters);
-
-        begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BULK_BEAN, null, Constants.SOURCE_FILE);
-        EmitUtils.null_constructor(this);
-        generateGet(target, getters);
-        generateSet(target, setters);
-        end_class();
-    }
-
-    private void generateGet(final Class target, final Method[] getters) {
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_VALUES, null);
-        if (getters.length >= 0) {
-            e.load_arg(0);
-            e.checkcast(Type.getType(target));
-            Local bean = e.make_local();
-            e.store_local(bean);
-            for (int i = 0; i < getters.length; i++) {
-                if (getters[i] != null) {
-                    MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]);
-                    e.load_arg(1);
-                    e.push(i);
-                    e.load_local(bean);
-                    e.invoke(getter);
-                    e.box(getter.getSignature().getReturnType());
-                    e.aastore();
-                }
-            }
-        }
-        e.return_value();
-        e.end_method();
-    }
-
-    private void generateSet(final Class target, final Method[] setters) {
-        // setPropertyValues
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_PROPERTY_VALUES, null);
-        if (setters.length > 0) {
-            Local index = e.make_local(Type.INT_TYPE);
-            e.push(0);
-            e.store_local(index);
-            e.load_arg(0);
-            e.checkcast(Type.getType(target));
-            e.load_arg(1);
-            Block handler = e.begin_block();
-            int lastIndex = 0;
-            for (int i = 0; i < setters.length; i++) {
-                if (setters[i] != null) {
-                    MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]);
-                    int diff = i - lastIndex;
-                    if (diff > 0) {
-                        e.iinc(index, diff);
-                        lastIndex = i;
-                    }
-                    e.dup2();
-                    e.aaload(i);
-                    e.unbox(setter.getSignature().getArgumentTypes()[0]);
-                    e.invoke(setter);
-                }
-            }
-            handler.end();
-            e.return_value();
-            e.catch_exception(handler, Constants.TYPE_THROWABLE);
-            e.new_instance(BULK_BEAN_EXCEPTION);
-            e.dup_x1();
-            e.swap();
-            e.load_local(index);
-            e.invoke_constructor(BULK_BEAN_EXCEPTION, CSTRUCT_EXCEPTION);
-            e.athrow();
-        } else {
-            e.return_value();
-        }
-        e.end_method();
-    }
-    
-    private static void validate(Class target,
-                                 String[] getters,
-                                 String[] setters,
-                                 Class[] types,
-                                 Method[] getters_out,
-                                 Method[] setters_out) {
-        int i = -1;
-        if (setters.length != types.length || getters.length != types.length) {
-            throw new BulkBeanException("accessor array length must be equal type array length", i);
-        }
-        try {
-            for (i = 0; i < types.length; i++) {
-                if (getters[i] != null) {
-                    Method method = ReflectUtils.findDeclaredMethod(target, getters[i], null);
-                    if (method.getReturnType() != types[i]) {
-                        throw new BulkBeanException("Specified type " + types[i] +
-                                                    " does not match declared type " + method.getReturnType(), i);
-                    }
-                    if (Modifier.isPrivate(method.getModifiers())) {
-                        throw new BulkBeanException("Property is private", i);
-                    }
-                    getters_out[i] = method;
-                }
-                if (setters[i] != null) {
-                    Method method = ReflectUtils.findDeclaredMethod(target, setters[i], new Class[]{ types[i] });
-                    if (Modifier.isPrivate(method.getModifiers()) ){
-                        throw new BulkBeanException("Property is private", i);
-                    }
-                    setters_out[i] = method;
-                }
-            }
-        } catch (NoSuchMethodException e) {
-            throw new BulkBeanException("Cannot find specified property", i);
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/BulkBeanException.java b/cglib-and-asm/src/org/mockito/cglib/beans/BulkBeanException.java
deleted file mode 100644
index 8df00dd..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/BulkBeanException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import org.mockito.cglib.core.CodeGenerationException;
-
-public class BulkBeanException extends RuntimeException
-{
-    private int index;
-    private Throwable cause;
-    
-    public BulkBeanException(String message, int index) {
-        super(message);
-        this.index = index;
-    }
-
-    public BulkBeanException(Throwable cause, int index) {
-        super(cause.getMessage());
-        this.index = index;
-        this.cause = cause;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-    
-    public Throwable getCause() {
-        return cause;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/FixedKeySet.java b/cglib-and-asm/src/org/mockito/cglib/beans/FixedKeySet.java
deleted file mode 100644
index af371c9..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/FixedKeySet.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.util.*;
-
-public /* need it for class loading  */ class FixedKeySet extends AbstractSet {
-    private Set set;
-    private int size;
-
-    public FixedKeySet(String[] keys) {
-        size = keys.length;
-        set = Collections.unmodifiableSet(new HashSet(Arrays.asList(keys)));
-    }
-
-    public Iterator iterator() {
-        return set.iterator();
-    }
-
-    public int size() {
-        return size;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/beans/ImmutableBean.java b/cglib-and-asm/src/org/mockito/cglib/beans/ImmutableBean.java
deleted file mode 100644
index 936478b..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/beans/ImmutableBean.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.beans;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Method;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * @author Chris Nokleberg
- */
-public class ImmutableBean
-{
-    private static final Type ILLEGAL_STATE_EXCEPTION =
-      TypeUtils.parseType("IllegalStateException");
-    private static final Signature CSTRUCT_OBJECT =
-      TypeUtils.parseConstructor("Object");
-    private static final Class[] OBJECT_CLASSES = { Object.class };
-    private static final String FIELD_NAME = "CGLIB$RWBean";
-
-    private ImmutableBean() {
-    }
-
-    public static Object create(Object bean) {
-        Generator gen = new Generator();
-        gen.setBean(bean);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(ImmutableBean.class.getName());
-        private Object bean;
-        private Class target;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        public void setBean(Object bean) {
-            this.bean = bean;
-            target = bean.getClass();
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return target.getClassLoader();
-        }
-
-        public Object create() {
-            String name = target.getName();
-            setNamePrefix(name);
-            return super.create(name);
-        }
-
-        public void generateClass(ClassVisitor v) {
-            Type targetType = Type.getType(target);
-            ClassEmitter ce = new ClassEmitter(v);
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           targetType,
-                           null,
-                           Constants.SOURCE_FILE);
-
-            ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null);
-
-            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
-            e.load_this();
-            e.super_invoke_constructor();
-            e.load_this();
-            e.load_arg(0);
-            e.checkcast(targetType);
-            e.putfield(FIELD_NAME);
-            e.return_value();
-            e.end_method();
-
-            PropertyDescriptor[] descriptors = ReflectUtils.getBeanProperties(target);
-            Method[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false);
-            Method[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true);
-
-            for (int i = 0; i < getters.length; i++) {
-                MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]);
-                e = EmitUtils.begin_method(ce, getter, Constants.ACC_PUBLIC);
-                e.load_this();
-                e.getfield(FIELD_NAME);
-                e.invoke(getter);
-                e.return_value();
-                e.end_method();
-            }
-
-            for (int i = 0; i < setters.length; i++) {
-                MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]);
-                e = EmitUtils.begin_method(ce, setter, Constants.ACC_PUBLIC);
-                e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable");
-                e.end_method();
-            }
-
-            ce.end_class();
-        }
-
-        protected Object firstInstance(Class type) {
-            return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object[]{ bean });
-        }
-
-        // TODO: optimize
-        protected Object nextInstance(Object instance) {
-            return firstInstance(instance.getClass());
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/AbstractClassGenerator.java b/cglib-and-asm/src/org/mockito/cglib/core/AbstractClassGenerator.java
deleted file mode 100644
index 44ca7aa..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/AbstractClassGenerator.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.io.*;
-import java.util.*;
-import java.lang.ref.*;
-
-import org.mockito.asm.ClassReader;
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.ClassWriter;
-import org.mockito.asm.Type;
-
-/**
- * Abstract class for all code-generating CGLIB utilities.
- * In addition to caching generated classes for performance, it provides hooks for
- * customizing the <code>ClassLoader</code>, name of the generated class, and transformations
- * applied before generation.
- */
-abstract public class AbstractClassGenerator
-implements ClassGenerator
-{
-    private static final Object NAME_KEY = new Object();
-    private static final ThreadLocal CURRENT = new ThreadLocal();
-
-    private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
-    private NamingPolicy namingPolicy = DefaultNamingPolicy.INSTANCE;
-    private Source source;
-    private ClassLoader classLoader;
-    private String namePrefix;
-    private Object key;
-    private boolean useCache = true;
-    private String className;
-    private boolean attemptLoad;
-
-    protected static class Source {
-        String name;
-        Map cache = new WeakHashMap();
-        public Source(String name) {
-            this.name = name;
-        }
-    }
-
-    protected AbstractClassGenerator(Source source) {
-        this.source = source;
-    }
-
-    protected void setNamePrefix(String namePrefix) {
-        this.namePrefix = namePrefix;
-    }
-
-    final protected String getClassName() {
-        if (className == null)
-            className = getClassName(getClassLoader());
-        return className;
-    }
-
-    private String getClassName(final ClassLoader loader) {
-        final Set nameCache = getClassNameCache(loader);
-        return namingPolicy.getClassName(namePrefix, source.name, key, new Predicate() {
-            public boolean evaluate(Object arg) {
-                return nameCache.contains(arg);
-            }
-        });
-    }
-
-    private Set getClassNameCache(ClassLoader loader) {
-        return (Set)((Map)source.cache.get(loader)).get(NAME_KEY);
-    }
-
-    /**
-     * Set the <code>ClassLoader</code> in which the class will be generated.
-     * Concrete subclasses of <code>AbstractClassGenerator</code> (such as <code>Enhancer</code>)
-     * will try to choose an appropriate default if this is unset.
-     * <p>
-     * Classes are cached per-<code>ClassLoader</code> using a <code>WeakHashMap</code>, to allow
-     * the generated classes to be removed when the associated loader is garbage collected.
-     * @param classLoader the loader to generate the new class with, or null to use the default
-     */
-    public void setClassLoader(ClassLoader classLoader) {
-        this.classLoader = classLoader;
-    }
-
-    /**
-     * Override the default naming policy.
-     * @see DefaultNamingPolicy
-     * @param namingPolicy the custom policy, or null to use the default
-     */
-    public void setNamingPolicy(NamingPolicy namingPolicy) {
-        if (namingPolicy == null)
-            namingPolicy = DefaultNamingPolicy.INSTANCE;
-        this.namingPolicy = namingPolicy;
-    }
-
-    /**
-     * @see #setNamingPolicy
-     */
-    public NamingPolicy getNamingPolicy() {
-        return namingPolicy;
-    }
-
-    /**
-     * Whether use and update the static cache of generated classes
-     * for a class with the same properties. Default is <code>true</code>.
-     */
-    public void setUseCache(boolean useCache) {
-        this.useCache = useCache;
-    }
-
-    /**
-     * @see #setUseCache
-     */
-    public boolean getUseCache() {
-        return useCache;
-    }
-
-    /**
-     * If set, CGLIB will attempt to load classes from the specified
-     * <code>ClassLoader</code> before generating them. Because generated
-     * class names are not guaranteed to be unique, the default is <code>false</code>.
-     */
-    public void setAttemptLoad(boolean attemptLoad) {
-        this.attemptLoad = attemptLoad;
-    }
-
-    public boolean getAttemptLoad() {
-        return attemptLoad;
-    }
-    
-    /**
-     * Set the strategy to use to create the bytecode from this generator.
-     * By default an instance of {@see DefaultGeneratorStrategy} is used.
-     */
-    public void setStrategy(GeneratorStrategy strategy) {
-        if (strategy == null)
-            strategy = DefaultGeneratorStrategy.INSTANCE;
-        this.strategy = strategy;
-    }
-
-    /**
-     * @see #setStrategy
-     */
-    public GeneratorStrategy getStrategy() {
-        return strategy;
-    }
-
-    /**
-     * Used internally by CGLIB. Returns the <code>AbstractClassGenerator</code>
-     * that is being used to generate a class in the current thread.
-     */
-    public static AbstractClassGenerator getCurrent() {
-        return (AbstractClassGenerator)CURRENT.get();
-    }
-
-    public ClassLoader getClassLoader() {
-        ClassLoader t = classLoader;
-        if (t == null) {
-            t = getDefaultClassLoader();
-        }
-        if (t == null) {
-            t = getClass().getClassLoader();
-        }
-        if (t == null) {
-            t = Thread.currentThread().getContextClassLoader();
-        }
-        if (t == null) {
-            throw new IllegalStateException("Cannot determine classloader");
-        }
-        return t;
-    }
-
-    abstract protected ClassLoader getDefaultClassLoader();
-
-    protected Object create(Object key) {
-        try {
-        	Class gen = null;
-        	
-            synchronized (source) {
-                ClassLoader loader = getClassLoader();
-                Map cache2 = null;
-                cache2 = (Map)source.cache.get(loader);
-                if (cache2 == null) {
-                    cache2 = new HashMap();
-                    cache2.put(NAME_KEY, new HashSet());
-                    source.cache.put(loader, cache2);
-                } else if (useCache) {
-                    Reference ref = (Reference)cache2.get(key);
-                    gen = (Class) (( ref == null ) ? null : ref.get()); 
-                }
-                if (gen == null) {
-                    Object save = CURRENT.get();
-                    CURRENT.set(this);
-                    try {
-                        this.key = key;
-                        
-                        if (attemptLoad) {
-                            try {
-                                gen = loader.loadClass(getClassName());
-                            } catch (ClassNotFoundException e) {
-                                // ignore
-                            }
-                        }
-                        if (gen == null) {
-                            byte[] b = strategy.generate(this);
-                            String className = ClassNameReader.getClassName(new ClassReader(b));
-                            getClassNameCache(loader).add(className);
-                            gen = ReflectUtils.defineClass(className, b, loader);
-                        }
-                       
-                        if (useCache) {
-                            cache2.put(key, new WeakReference(gen));
-                        }
-                        return firstInstance(gen);
-                    } finally {
-                        CURRENT.set(save);
-                    }
-                }
-            }
-            return firstInstance(gen);
-        } catch (RuntimeException e) {
-            throw e;
-        } catch (Error e) {
-            throw e;
-        } catch (Exception e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-
-    abstract protected Object firstInstance(Class type) throws Exception;
-    abstract protected Object nextInstance(Object instance) throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Block.java b/cglib-and-asm/src/org/mockito/cglib/core/Block.java
deleted file mode 100644
index 16dfbec..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Block.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Label;
-
-public class Block
-{
-    private CodeEmitter e;
-    private Label start;
-    private Label end;
-
-    public Block(CodeEmitter e) {
-        this.e = e;
-        start = e.mark();
-    }
-
-    public CodeEmitter getCodeEmitter() {
-        return e;
-    }
-
-    public void end() {
-        if (end != null) {
-            throw new IllegalStateException("end of label already set");
-        }
-        end = e.mark();
-    }
-    
-    public Label getStart() {
-        return start;
-    }
-
-    public Label getEnd() {
-        return end;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ClassEmitter.java b/cglib-and-asm/src/org/mockito/cglib/core/ClassEmitter.java
deleted file mode 100644
index d13891a..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ClassEmitter.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.io.*;
-import java.util.*;
-
-import org.mockito.asm.*;
-
-/**
- * @author Juozas Baliuka, Chris Nokleberg
- */
-public class ClassEmitter extends ClassAdapter {
-    private ClassInfo classInfo;
-    private Map fieldInfo;
-
-    private static int hookCounter;
-    private MethodVisitor rawStaticInit;
-    private CodeEmitter staticInit;
-    private CodeEmitter staticHook;
-    private Signature staticHookSig;
-
-    public ClassEmitter(ClassVisitor cv) {
-        super(null);
-        setTarget(cv);
-    }
-
-    public ClassEmitter() {
-        super(null);
-    }
-
-    public void setTarget(ClassVisitor cv) {
-        this.cv = cv;
-        fieldInfo = new HashMap();
-
-        // just to be safe
-        staticInit = staticHook = null;
-        staticHookSig = null;
-    }
-
-    synchronized private static int getNextHook() {
-        return ++hookCounter;
-    }
-
-    public ClassInfo getClassInfo() {
-        return classInfo;
-    }
-
-    public void begin_class(int version, final int access, String className, final Type superType, final Type[] interfaces, String source) {
-        final Type classType = Type.getType("L" + className.replace('.', '/') + ";");
-        classInfo = new ClassInfo() {
-            public Type getType() {
-                return classType;
-            }
-            public Type getSuperType() {
-                return (superType != null) ? superType : Constants.TYPE_OBJECT;
-            }
-            public Type[] getInterfaces() {
-                return interfaces;
-            }
-            public int getModifiers() {
-                return access;
-            }
-        };
-        cv.visit(version,
-                 access,
-                 classInfo.getType().getInternalName(),
-                 null,
-                 classInfo.getSuperType().getInternalName(),
-                 TypeUtils.toInternalNames(interfaces));
-        if (source != null)
-            cv.visitSource(source, null);
-        init();
-    }
-
-    public CodeEmitter getStaticHook() {
-         if (TypeUtils.isInterface(getAccess())) {
-             throw new IllegalStateException("static hook is invalid for this class");
-         }
-         if (staticHook == null) {
-             staticHookSig = new Signature("CGLIB$STATICHOOK" + getNextHook(), "()V");
-             staticHook = begin_method(Constants.ACC_STATIC,
-                                       staticHookSig,
-                                       null);
-             if (staticInit != null) {
-                 staticInit.invoke_static_this(staticHookSig);
-             }
-         }
-         return staticHook;
-    }
-
-    protected void init() {
-    }
-
-    public int getAccess() {
-        return classInfo.getModifiers();
-    }
-
-    public Type getClassType() {
-        return classInfo.getType();
-    }
-
-    public Type getSuperType() {
-        return classInfo.getSuperType();
-    }
-
-    public void end_class() {
-        if (staticHook != null && staticInit == null) {
-            // force creation of static init
-            begin_static();
-        }
-        if (staticInit != null) {
-            staticHook.return_value();
-            staticHook.end_method();
-            rawStaticInit.visitInsn(Constants.RETURN);
-            rawStaticInit.visitMaxs(0, 0);
-            staticInit = staticHook = null;
-            staticHookSig = null;
-        }
-        cv.visitEnd();
-    }
-
-    public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
-        if (classInfo == null)
-            throw new IllegalStateException("classInfo is null! " + this);
-        MethodVisitor v = cv.visitMethod(access,
-                                         sig.getName(),
-                                         sig.getDescriptor(),
-                                         null,
-                                         TypeUtils.toInternalNames(exceptions));
-        if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(getAccess())) {
-            rawStaticInit = v;
-            MethodVisitor wrapped = new MethodAdapter(v) {
-                public void visitMaxs(int maxStack, int maxLocals) {
-                    // ignore
-                }
-                public void visitInsn(int insn) {
-                    if (insn != Constants.RETURN) {
-                        super.visitInsn(insn);
-                    }
-                }
-            };
-            staticInit = new CodeEmitter(this, wrapped, access, sig, exceptions);
-            if (staticHook == null) {
-                // force static hook creation
-                getStaticHook();
-            } else {
-                staticInit.invoke_static_this(staticHookSig);
-            }
-            return staticInit;
-        } else if (sig.equals(staticHookSig)) {
-            return new CodeEmitter(this, v, access, sig, exceptions) {
-                public boolean isStaticHook() {
-                    return true;
-                }
-            };
-        } else {
-            return new CodeEmitter(this, v, access, sig, exceptions);
-        }
-    }
-
-    public CodeEmitter begin_static() {
-        return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null);
-    }
-
-    public void declare_field(int access, String name, Type type, Object value) {
-        FieldInfo existing = (FieldInfo)fieldInfo.get(name);
-        FieldInfo info = new FieldInfo(access, name, type, value);
-        if (existing != null) {
-            if (!info.equals(existing)) {
-                throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently");
-            }
-        } else {
-            fieldInfo.put(name, info);
-            cv.visitField(access, name, type.getDescriptor(), null, value);
-        }
-    }
-
-    // TODO: make public?
-    boolean isFieldDeclared(String name) {
-        return fieldInfo.get(name) != null;
-    }
-
-    FieldInfo getFieldInfo(String name) {
-        FieldInfo field = (FieldInfo)fieldInfo.get(name);
-        if (field == null) {
-            throw new IllegalArgumentException("Field " + name + " is not declared in " + getClassType().getClassName());
-        }
-        return field;
-    }
-    
-    static class FieldInfo {
-        int access;
-        String name;
-        Type type;
-        Object value;
-        
-        public FieldInfo(int access, String name, Type type, Object value) {
-            this.access = access;
-            this.name = name;
-            this.type = type;
-            this.value = value;
-        }
-
-        public boolean equals(Object o) {
-            if (o == null)
-                return false;
-            if (!(o instanceof FieldInfo))
-                return false;
-            FieldInfo other = (FieldInfo)o;
-            if (access != other.access ||
-                !name.equals(other.name) ||
-                !type.equals(other.type)) {
-                return false;
-            }
-            if ((value == null) ^ (other.value == null))
-                return false;
-            if (value != null && !value.equals(other.value))
-                return false;
-            return true;
-        }
-
-        public int hashCode() {
-            return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode());
-        }
-    }
-
-    public void visit(int version,
-                      int access,
-                      String name,
-                      String signature,
-                      String superName,
-                      String[] interfaces) {
-        begin_class(version,
-                    access,
-                    name.replace('/', '.'),
-                    TypeUtils.fromInternalName(superName),
-                    TypeUtils.fromInternalNames(interfaces),
-                    null); // TODO
-    }
-    
-    public void visitEnd() {
-        end_class();
-    }
-    
-    public FieldVisitor visitField(int access,
-                                   String name,
-                                   String desc,
-                                   String signature,
-                                   Object value) {
-        declare_field(access, name, Type.getType(desc), value);
-        return null; // TODO
-    }
-    
-    public MethodVisitor visitMethod(int access,
-                                     String name,
-                                     String desc,
-                                     String signature,
-                                     String[] exceptions) {
-        return begin_method(access,
-                            new Signature(name, desc),
-                            TypeUtils.fromInternalNames(exceptions));        
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ClassGenerator.java b/cglib-and-asm/src/org/mockito/cglib/core/ClassGenerator.java
deleted file mode 100644
index 116c19d..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ClassGenerator.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.ClassVisitor;
-
-public interface ClassGenerator {
-    void generateClass(ClassVisitor v) throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ClassInfo.java b/cglib-and-asm/src/org/mockito/cglib/core/ClassInfo.java
deleted file mode 100644
index 4cb763c..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ClassInfo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.Type;
-
-abstract public class ClassInfo {
-
-    protected ClassInfo() {
-    }
-
-    abstract public Type getType();
-    abstract public Type getSuperType();
-    abstract public Type[] getInterfaces();
-    abstract public int getModifiers();
-
-    public boolean equals(Object o) {
-        if (o == null)
-            return false;
-        if (!(o instanceof ClassInfo))
-            return false;
-        return getType().equals(((ClassInfo)o).getType());
-    }
-
-    public int hashCode() {
-        return getType().hashCode();
-    }
-
-    public String toString() {
-        // TODO: include modifiers, superType, interfaces
-        return getType().getClassName();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ClassNameReader.java b/cglib-and-asm/src/org/mockito/cglib/core/ClassNameReader.java
deleted file mode 100644
index 11073f7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ClassNameReader.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.ClassAdapter;
-import org.mockito.asm.ClassReader;
-
-import java.util.*;
-
-// TODO: optimize (ClassReader buffers entire class before accept)
-public class ClassNameReader {
-    private ClassNameReader() {
-    }
-
-    private static final EarlyExitException EARLY_EXIT = new EarlyExitException();
-    private static class EarlyExitException extends RuntimeException { }
-    
-    public static String getClassName(ClassReader r) {
-    
-        return getClassInfo(r)[0];
-      
-    }
-    
-    public static String[] getClassInfo(ClassReader r) {
-        final List array = new ArrayList();
-        try {
-            r.accept(new ClassAdapter(null) {
-                public void visit(int version,
-                                  int access,
-                                  String name,
-                                  String signature,
-                                  String superName,
-                                  String[] interfaces) {
-                    array.add( name.replace('/', '.') );
-                    if(superName != null){
-                      array.add( superName.replace('/', '.') );
-                    }
-                    for(int i = 0; i < interfaces.length; i++  ){
-                       array.add( interfaces[i].replace('/', '.') );
-                    }
-                    
-                    throw EARLY_EXIT;
-                }
-            }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
-        } catch (EarlyExitException e) { }
-        
-        return (String[])array.toArray( new String[]{} );
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ClassesKey.java b/cglib-and-asm/src/org/mockito/cglib/core/ClassesKey.java
deleted file mode 100644
index 4abf507..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ClassesKey.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-public class ClassesKey {
-    private static final Key FACTORY = (Key)KeyFactory.create(Key.class, KeyFactory.OBJECT_BY_CLASS);
-    
-    interface Key {
-        Object newInstance(Object[] array);
-    }
-
-    private ClassesKey() {
-    }
-
-    public static Object create(Object[] array) {
-        return FACTORY.newInstance(array);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/CodeEmitter.java b/cglib-and-asm/src/org/mockito/cglib/core/CodeEmitter.java
deleted file mode 100644
index c94e91a..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/CodeEmitter.java
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.io.*;
-import java.util.*;
-
-import org.mockito.asm.*;
-
-/**
- * @author Juozas Baliuka, Chris Nokleberg
- */
-public class CodeEmitter extends LocalVariablesSorter {
-    private static final Signature BOOLEAN_VALUE =
-      TypeUtils.parseSignature("boolean booleanValue()");
-    private static final Signature CHAR_VALUE =
-      TypeUtils.parseSignature("char charValue()");
-    private static final Signature LONG_VALUE =
-      TypeUtils.parseSignature("long longValue()");
-    private static final Signature DOUBLE_VALUE =
-      TypeUtils.parseSignature("double doubleValue()");
-    private static final Signature FLOAT_VALUE =
-      TypeUtils.parseSignature("float floatValue()");
-    private static final Signature INT_VALUE =
-      TypeUtils.parseSignature("int intValue()");
-    private static final Signature CSTRUCT_NULL =
-      TypeUtils.parseConstructor("");
-    private static final Signature CSTRUCT_STRING =
-      TypeUtils.parseConstructor("String");
-
-    public static final int ADD = Constants.IADD;
-    public static final int MUL = Constants.IMUL;
-    public static final int XOR = Constants.IXOR;
-    public static final int USHR = Constants.IUSHR;
-    public static final int SUB = Constants.ISUB;
-    public static final int DIV = Constants.IDIV;
-    public static final int NEG = Constants.INEG;
-    public static final int REM = Constants.IREM;
-    public static final int AND = Constants.IAND;
-    public static final int OR = Constants.IOR;
-
-    public static final int GT = Constants.IFGT;
-    public static final int LT = Constants.IFLT;
-    public static final int GE = Constants.IFGE;
-    public static final int LE = Constants.IFLE;
-    public static final int NE = Constants.IFNE;
-    public static final int EQ = Constants.IFEQ;
-
-    private ClassEmitter ce;
-    private State state;
-
-    private static class State
-    extends MethodInfo
-    {
-        ClassInfo classInfo;
-        int access;
-        Signature sig;
-        Type[] argumentTypes;
-        int localOffset;
-        Type[] exceptionTypes;
-
-        State(ClassInfo classInfo, int access, Signature sig, Type[] exceptionTypes) {
-            this.classInfo = classInfo;
-            this.access = access;
-            this.sig = sig;
-            this.exceptionTypes = exceptionTypes;
-            localOffset = TypeUtils.isStatic(access) ? 0 : 1;
-            argumentTypes = sig.getArgumentTypes();
-        }
-
-        public ClassInfo getClassInfo() {
-            return classInfo;
-        }
-
-        public int getModifiers() {
-            return access;
-        }
-
-        public Signature getSignature() {
-            return sig;
-        }
-
-        public Type[] getExceptionTypes() {
-            return exceptionTypes;
-        }
-
-        public Attribute getAttribute() {
-            // TODO
-            return null;
-        }
-    }
-
-    CodeEmitter(ClassEmitter ce, MethodVisitor mv, int access, Signature sig, Type[] exceptionTypes) {
-        super(access, sig.getDescriptor(), mv);
-        this.ce = ce;
-        state = new State(ce.getClassInfo(), access, sig, exceptionTypes);
-    }
-
-    public CodeEmitter(CodeEmitter wrap) {
-        super(wrap);
-        this.ce = wrap.ce;
-        this.state = wrap.state;
-    }
-
-    public boolean isStaticHook() {
-        return false;
-    }
-
-    public Signature getSignature() {
-        return state.sig;
-    }
-
-    public Type getReturnType() {
-        return state.sig.getReturnType();
-    }
-
-    public MethodInfo getMethodInfo() {
-        return state;
-    }
-
-    public ClassEmitter getClassEmitter() {
-        return ce;
-    }
-
-    public void end_method() {
-        visitMaxs(0, 0);
-    }
-
-    public Block begin_block() {
-        return new Block(this);
-    }
-
-    public void catch_exception(Block block, Type exception) {
-        if (block.getEnd() == null) {
-            throw new IllegalStateException("end of block is unset");
-        }
-        mv.visitTryCatchBlock(block.getStart(),
-                              block.getEnd(),
-                              mark(),
-                              exception.getInternalName());
-    }
-
-    public void goTo(Label label) { mv.visitJumpInsn(Constants.GOTO, label); }
-    public void ifnull(Label label) { mv.visitJumpInsn(Constants.IFNULL, label); }
-    public void ifnonnull(Label label) { mv.visitJumpInsn(Constants.IFNONNULL, label); }
-
-    public void if_jump(int mode, Label label) {
-        mv.visitJumpInsn(mode, label);
-    }
-
-    public void if_icmp(int mode, Label label) {
-        if_cmp(Type.INT_TYPE, mode, label);
-    }
-
-    public void if_cmp(Type type, int mode, Label label) {
-        int intOp = -1;
-        int jumpmode = mode;
-        switch (mode) {
-        case GE: jumpmode = LT; break;
-        case LE: jumpmode = GT; break;
-        }
-        switch (type.getSort()) {
-        case Type.LONG:
-            mv.visitInsn(Constants.LCMP);
-            break;
-        case Type.DOUBLE:
-            mv.visitInsn(Constants.DCMPG);
-            break;
-        case Type.FLOAT:
-            mv.visitInsn(Constants.FCMPG);
-            break;
-        case Type.ARRAY:
-        case Type.OBJECT:
-            switch (mode) {
-            case EQ:
-                mv.visitJumpInsn(Constants.IF_ACMPEQ, label);
-                return;
-            case NE:
-                mv.visitJumpInsn(Constants.IF_ACMPNE, label);
-                return;
-            }
-            throw new IllegalArgumentException("Bad comparison for type " + type);
-        default:
-            switch (mode) {
-            case EQ: intOp = Constants.IF_ICMPEQ; break;
-            case NE: intOp = Constants.IF_ICMPNE; break;
-            case GE: swap(); /* fall through */
-            case LT: intOp = Constants.IF_ICMPLT; break;
-            case LE: swap(); /* fall through */
-            case GT: intOp = Constants.IF_ICMPGT; break;
-            }
-            mv.visitJumpInsn(intOp, label);
-            return;
-        }
-        if_jump(jumpmode, label);
-    }
-
-    public void pop() { mv.visitInsn(Constants.POP); }
-    public void pop2() { mv.visitInsn(Constants.POP2); }
-    public void dup() { mv.visitInsn(Constants.DUP); }
-    public void dup2() { mv.visitInsn(Constants.DUP2); }
-    public void dup_x1() { mv.visitInsn(Constants.DUP_X1); }
-    public void dup_x2() { mv.visitInsn(Constants.DUP_X2); }
-    public void dup2_x1() { mv.visitInsn(Constants.DUP2_X1); }
-    public void dup2_x2() { mv.visitInsn(Constants.DUP2_X2); }
-    public void swap() { mv.visitInsn(Constants.SWAP); }
-    public void aconst_null() { mv.visitInsn(Constants.ACONST_NULL); }
-
-    public void swap(Type prev, Type type) {
-        if (type.getSize() == 1) {
-            if (prev.getSize() == 1) {
-                swap(); // same as dup_x1(), pop();
-            } else {
-                dup_x2();
-                pop();
-            }
-        } else {
-            if (prev.getSize() == 1) {
-                dup2_x1();
-                pop2();
-            } else {
-                dup2_x2();
-                pop2();
-            }
-        }
-    }
-
-    public void monitorenter() { mv.visitInsn(Constants.MONITORENTER); }
-    public void monitorexit() { mv.visitInsn(Constants.MONITOREXIT); }
-
-    public void math(int op, Type type) { mv.visitInsn(type.getOpcode(op)); }
-
-    public void array_load(Type type) { mv.visitInsn(type.getOpcode(Constants.IALOAD)); }
-    public void array_store(Type type) { mv.visitInsn(type.getOpcode(Constants.IASTORE)); }
-
-    /**
-     * Casts from one primitive numeric type to another
-     */
-    public void cast_numeric(Type from, Type to) {
-        if (from != to) {
-            if (from == Type.DOUBLE_TYPE) {
-                if (to == Type.FLOAT_TYPE) {
-                    mv.visitInsn(Constants.D2F);
-                } else if (to == Type.LONG_TYPE) {
-                    mv.visitInsn(Constants.D2L);
-                } else {
-                    mv.visitInsn(Constants.D2I);
-                    cast_numeric(Type.INT_TYPE, to);
-                }
-            } else if (from == Type.FLOAT_TYPE) {
-                if (to == Type.DOUBLE_TYPE) {
-                    mv.visitInsn(Constants.F2D);
-                } else if (to == Type.LONG_TYPE) {
-                    mv.visitInsn(Constants.F2L);
-                } else {
-                    mv.visitInsn(Constants.F2I);
-                    cast_numeric(Type.INT_TYPE, to);
-                }
-            } else if (from == Type.LONG_TYPE) {
-                if (to == Type.DOUBLE_TYPE) {
-                    mv.visitInsn(Constants.L2D);
-                } else if (to == Type.FLOAT_TYPE) {
-                    mv.visitInsn(Constants.L2F);
-                } else {
-                    mv.visitInsn(Constants.L2I);
-                    cast_numeric(Type.INT_TYPE, to);
-                }
-            } else {
-                if (to == Type.BYTE_TYPE) {
-                    mv.visitInsn(Constants.I2B);
-                } else if (to == Type.CHAR_TYPE) {
-                    mv.visitInsn(Constants.I2C);
-                } else if (to == Type.DOUBLE_TYPE) {
-                    mv.visitInsn(Constants.I2D);
-                } else if (to == Type.FLOAT_TYPE) {
-                    mv.visitInsn(Constants.I2F);
-                } else if (to == Type.LONG_TYPE) {
-                    mv.visitInsn(Constants.I2L);
-                } else if (to == Type.SHORT_TYPE) {
-                    mv.visitInsn(Constants.I2S);
-                }
-            }
-        }
-    }
-
-    public void push(int i) {
-        if (i < -1) {
-            mv.visitLdcInsn(new Integer(i));
-        } else if (i <= 5) {
-            mv.visitInsn(TypeUtils.ICONST(i));
-        } else if (i <= Byte.MAX_VALUE) {
-            mv.visitIntInsn(Constants.BIPUSH, i);
-        } else if (i <= Short.MAX_VALUE) {
-            mv.visitIntInsn(Constants.SIPUSH, i);
-        } else {
-            mv.visitLdcInsn(new Integer(i));
-        }
-    }
-    
-    public void push(long value) {
-        if (value == 0L || value == 1L) {
-            mv.visitInsn(TypeUtils.LCONST(value));
-        } else {
-            mv.visitLdcInsn(new Long(value));
-        }
-    }
-    
-    public void push(float value) {
-        if (value == 0f || value == 1f || value == 2f) {
-            mv.visitInsn(TypeUtils.FCONST(value));
-        } else {
-            mv.visitLdcInsn(new Float(value));
-        }
-    }
-    public void push(double value) {
-        if (value == 0d || value == 1d) {
-            mv.visitInsn(TypeUtils.DCONST(value));
-        } else {
-            mv.visitLdcInsn(new Double(value));
-        }
-    }
-    
-    public void push(String value) {
-        mv.visitLdcInsn(value);
-    }
-
-    public void newarray() {
-        newarray(Constants.TYPE_OBJECT);
-    }
-
-    public void newarray(Type type) {
-        if (TypeUtils.isPrimitive(type)) {
-            mv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type));
-        } else {
-            emit_type(Constants.ANEWARRAY, type);
-        }
-    }
-    
-    public void arraylength() {
-        mv.visitInsn(Constants.ARRAYLENGTH);
-    }
-    
-    public void load_this() {
-        if (TypeUtils.isStatic(state.access)) {
-            throw new IllegalStateException("no 'this' pointer within static method");
-        }
-        mv.visitVarInsn(Constants.ALOAD, 0);
-    }
-    
-    /**
-     * Pushes all of the arguments of the current method onto the stack.
-     */
-    public void load_args() {
-        load_args(0, state.argumentTypes.length);
-    }
-
-    /**
-     * Pushes the specified argument of the current method onto the stack.
-     * @param index the zero-based index into the argument list
-     */
-    public void load_arg(int index) {
-        load_local(state.argumentTypes[index],
-                   state.localOffset + skipArgs(index));
-    }
-
-    // zero-based (see load_this)
-    public void load_args(int fromArg, int count) {
-        int pos = state.localOffset + skipArgs(fromArg);
-        for (int i = 0; i < count; i++) {
-            Type t = state.argumentTypes[fromArg + i];
-            load_local(t, pos);
-            pos += t.getSize();
-        }
-    }
-    
-    private int skipArgs(int numArgs) {
-        int amount = 0;
-        for (int i = 0; i < numArgs; i++) {
-            amount += state.argumentTypes[i].getSize();
-        }
-        return amount;
-    }
-
-    private void load_local(Type t, int pos) {
-        // TODO: make t == null ok?
-        mv.visitVarInsn(t.getOpcode(Constants.ILOAD), pos);
-    }
-
-    private void store_local(Type t, int pos) {
-        // TODO: make t == null ok?
-        mv.visitVarInsn(t.getOpcode(Constants.ISTORE), pos);
-    }
-    
-    public void iinc(Local local, int amount) {
-        mv.visitIincInsn(local.getIndex(), amount);
-    }
-    
-    public void store_local(Local local) {
-        store_local(local.getType(), local.getIndex());
-    }
-    
-    public void load_local(Local local) {
-        load_local(local.getType(), local.getIndex());
-    }
-
-    public void return_value() {
-        mv.visitInsn(state.sig.getReturnType().getOpcode(Constants.IRETURN));
-    }
-
-    public void getfield(String name) {
-        ClassEmitter.FieldInfo info = ce.getFieldInfo(name);
-        int opcode = TypeUtils.isStatic(info.access) ? Constants.GETSTATIC : Constants.GETFIELD;
-        emit_field(opcode, ce.getClassType(), name, info.type);
-    }
-    
-    public void putfield(String name) {
-        ClassEmitter.FieldInfo info = ce.getFieldInfo(name);
-        int opcode = TypeUtils.isStatic(info.access) ? Constants.PUTSTATIC : Constants.PUTFIELD;
-        emit_field(opcode, ce.getClassType(), name, info.type);
-    }
-
-    public void super_getfield(String name, Type type) {
-        emit_field(Constants.GETFIELD, ce.getSuperType(), name, type);
-    }
-    
-    public void super_putfield(String name, Type type) {
-        emit_field(Constants.PUTFIELD, ce.getSuperType(), name, type);
-    }
-
-    public void super_getstatic(String name, Type type) {
-        emit_field(Constants.GETSTATIC, ce.getSuperType(), name, type);
-    }
-    
-    public void super_putstatic(String name, Type type) {
-        emit_field(Constants.PUTSTATIC, ce.getSuperType(), name, type);
-    }
-
-    public void getfield(Type owner, String name, Type type) {
-        emit_field(Constants.GETFIELD, owner, name, type);
-    }
-    
-    public void putfield(Type owner, String name, Type type) {
-        emit_field(Constants.PUTFIELD, owner, name, type);
-    }
-
-    public void getstatic(Type owner, String name, Type type) {
-        emit_field(Constants.GETSTATIC, owner, name, type);
-    }
-    
-    public void putstatic(Type owner, String name, Type type) {
-        emit_field(Constants.PUTSTATIC, owner, name, type);
-    }
-
-    // package-protected for EmitUtils, try to fix
-    void emit_field(int opcode, Type ctype, String name, Type ftype) {
-        mv.visitFieldInsn(opcode,
-                          ctype.getInternalName(),
-                          name,
-                          ftype.getDescriptor());
-    }
-
-    public void super_invoke() {
-        super_invoke(state.sig);
-    }
-
-    public void super_invoke(Signature sig) {
-        emit_invoke(Constants.INVOKESPECIAL, ce.getSuperType(), sig);
-    }
-
-    public void invoke_constructor(Type type) {
-        invoke_constructor(type, CSTRUCT_NULL);
-    }
-
-    public void super_invoke_constructor() {
-        invoke_constructor(ce.getSuperType());
-    }
-    
-    public void invoke_constructor_this() {
-        invoke_constructor(ce.getClassType());
-    }
-
-    private void emit_invoke(int opcode, Type type, Signature sig) {
-        if (sig.getName().equals(Constants.CONSTRUCTOR_NAME) &&
-            ((opcode == Constants.INVOKEVIRTUAL) ||
-             (opcode == Constants.INVOKESTATIC))) {
-            // TODO: error
-        }
-        mv.visitMethodInsn(opcode,
-                           type.getInternalName(),
-                           sig.getName(),
-                           sig.getDescriptor());
-    }
-    
-    public void invoke_interface(Type owner, Signature sig) {
-        emit_invoke(Constants.INVOKEINTERFACE, owner, sig);
-    }
-
-    public void invoke_virtual(Type owner, Signature sig) {
-        emit_invoke(Constants.INVOKEVIRTUAL, owner, sig);
-    }
-
-    public void invoke_static(Type owner, Signature sig) {
-        emit_invoke(Constants.INVOKESTATIC, owner, sig);
-    }
-
-    public void invoke_virtual_this(Signature sig) {
-        invoke_virtual(ce.getClassType(), sig);
-    }
-
-    public void invoke_static_this(Signature sig) {
-        invoke_static(ce.getClassType(), sig);
-    }
-
-    public void invoke_constructor(Type type, Signature sig) {
-        emit_invoke(Constants.INVOKESPECIAL, type, sig);
-    }
-
-    public void invoke_constructor_this(Signature sig) {
-        invoke_constructor(ce.getClassType(), sig);
-    }
-
-    public void super_invoke_constructor(Signature sig) {
-        invoke_constructor(ce.getSuperType(), sig);
-    }
-    
-    public void new_instance_this() {
-        new_instance(ce.getClassType());
-    }
-
-    public void new_instance(Type type) {
-        emit_type(Constants.NEW, type);
-    }
-
-    private void emit_type(int opcode, Type type) {
-        String desc;
-        if (TypeUtils.isArray(type)) {
-            desc = type.getDescriptor();
-        } else {
-            desc = type.getInternalName();
-        }
-        mv.visitTypeInsn(opcode, desc);
-    }
-
-    public void aaload(int index) {
-        push(index);
-        aaload();
-    }
-
-    public void aaload() { mv.visitInsn(Constants.AALOAD); }
-    public void aastore() { mv.visitInsn(Constants.AASTORE); }
-    public void athrow() { mv.visitInsn(Constants.ATHROW); }
-
-    public Label make_label() {
-        return new Label();
-    }
-    
-    public Local make_local() {
-        return make_local(Constants.TYPE_OBJECT);
-    }
-    
-    public Local make_local(Type type) {
-        return new Local(newLocal(type.getSize()), type);
-    }
-
-    public void checkcast_this() {
-        checkcast(ce.getClassType());
-    }
-    
-    public void checkcast(Type type) {
-        if (!type.equals(Constants.TYPE_OBJECT)) {
-            emit_type(Constants.CHECKCAST, type);
-        }
-    }
-
-    public void instance_of(Type type) {
-        emit_type(Constants.INSTANCEOF, type);
-    }
-    
-    public void instance_of_this() {
-        instance_of(ce.getClassType());
-    }
-
-    public void process_switch(int[] keys, ProcessSwitchCallback callback) {
-        float density;
-        if (keys.length == 0) {
-            density = 0;
-        } else {
-            density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1);
-        }
-        process_switch(keys, callback, density >= 0.5f);
-    }
-
-    public void process_switch(int[] keys, ProcessSwitchCallback callback, boolean useTable) {
-        if (!isSorted(keys))
-            throw new IllegalArgumentException("keys to switch must be sorted ascending");
-        Label def = make_label();
-        Label end = make_label();
-
-        try {
-            if (keys.length > 0) {
-                int len = keys.length;
-                int min = keys[0];
-                int max = keys[len - 1];
-                int range = max - min + 1;
-
-                if (useTable) {
-                    Label[] labels = new Label[range];
-                    Arrays.fill(labels, def);
-                    for (int i = 0; i < len; i++) {
-                        labels[keys[i] - min] = make_label();
-                    }
-                    mv.visitTableSwitchInsn(min, max, def, labels);
-                    for (int i = 0; i < range; i++) {
-                        Label label = labels[i];
-                        if (label != def) {
-                            mark(label);
-                            callback.processCase(i + min, end);
-                        }
-                    }
-                } else {
-                    Label[] labels = new Label[len];
-                    for (int i = 0; i < len; i++) {
-                        labels[i] = make_label();
-                    }
-                    mv.visitLookupSwitchInsn(def, keys, labels);
-                    for (int i = 0; i < len; i++) {
-                        mark(labels[i]);
-                        callback.processCase(keys[i], end);
-                    }
-                }
-            }
-
-            mark(def);
-            callback.processDefault();
-            mark(end);
-
-        } catch (RuntimeException e) {
-            throw e;
-        } catch (Error e) {
-            throw e;
-        } catch (Exception e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-
-    private static boolean isSorted(int[] keys) {
-        for (int i = 1; i < keys.length; i++) {
-            if (keys[i] < keys[i - 1])
-                return false;
-        }
-        return true;
-    }
-
-    public void mark(Label label) {
-        mv.visitLabel(label);
-    }
-
-    Label mark() {
-        Label label = make_label();
-        mv.visitLabel(label);
-        return label;
-    }
-
-    public void push(boolean value) {
-        push(value ? 1 : 0);
-    }
-
-    /**
-     * Toggles the integer on the top of the stack from 1 to 0 or vice versa
-     */
-    public void not() {
-        push(1);
-        math(XOR, Type.INT_TYPE);
-    }
-
-    public void throw_exception(Type type, String msg) {
-        new_instance(type);
-        dup();
-        push(msg);
-        invoke_constructor(type, CSTRUCT_STRING);
-        athrow();
-    }
-
-    /**
-     * If the argument is a primitive class, replaces the primitive value
-     * on the top of the stack with the wrapped (Object) equivalent. For
-     * example, char -> Character.
-     * If the class is Void, a null is pushed onto the stack instead.
-     * @param type the class indicating the current type of the top stack value
-     */
-    public void box(Type type) {
-        if (TypeUtils.isPrimitive(type)) {
-            if (type == Type.VOID_TYPE) {
-                aconst_null();
-            } else {
-                Type boxed = TypeUtils.getBoxedType(type);
-                new_instance(boxed);
-                if (type.getSize() == 2) {
-                    // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
-                    dup_x2();
-                    dup_x2();
-                    pop();
-                } else {
-                    // p -> po -> opo -> oop -> o
-                    dup_x1();
-                    swap();
-                }
-                invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type }));
-            }
-        }
-    }
-    
-    /**
-     * If the argument is a primitive class, replaces the object
-     * on the top of the stack with the unwrapped (primitive)
-     * equivalent. For example, Character -> char.
-     * @param type the class indicating the desired type of the top stack value
-     * @return true if the value was unboxed
-     */
-    public void unbox(Type type) {
-        Type t = Constants.TYPE_NUMBER;
-        Signature sig = null;
-        switch (type.getSort()) {
-        case Type.VOID:
-            return;
-        case Type.CHAR:
-            t = Constants.TYPE_CHARACTER;
-            sig = CHAR_VALUE;
-            break;
-        case Type.BOOLEAN:
-            t = Constants.TYPE_BOOLEAN;
-            sig = BOOLEAN_VALUE;
-            break;
-        case Type.DOUBLE:
-            sig = DOUBLE_VALUE;
-            break;
-        case Type.FLOAT:
-            sig = FLOAT_VALUE;
-            break;
-        case Type.LONG:
-            sig = LONG_VALUE;
-            break;
-        case Type.INT:
-        case Type.SHORT:
-        case Type.BYTE:
-            sig = INT_VALUE;
-        }
-
-        if (sig == null) {
-            checkcast(type);
-        } else {
-            checkcast(t);
-            invoke_virtual(t, sig);
-        }
-    }
-
-    /**
-     * Allocates and fills an Object[] array with the arguments to the
-     * current method. Primitive values are inserted as their boxed
-     * (Object) equivalents.
-     */
-    public void create_arg_array() {
-        /* generates:
-           Object[] args = new Object[]{ arg1, new Integer(arg2) };
-         */
-
-        push(state.argumentTypes.length);
-        newarray();
-        for (int i = 0; i < state.argumentTypes.length; i++) {
-            dup();
-            push(i);
-            load_arg(i);
-            box(state.argumentTypes[i]);
-            aastore();
-        }
-    }
-
-
-    /**
-     * Pushes a zero onto the stack if the argument is a primitive class, or a null otherwise.
-     */
-    public void zero_or_null(Type type) {
-        if (TypeUtils.isPrimitive(type)) {
-            switch (type.getSort()) {
-            case Type.DOUBLE:
-                push(0d);
-                break;
-            case Type.LONG:
-                push(0L);
-                break;
-            case Type.FLOAT:
-                push(0f);
-                break;
-            case Type.VOID:
-                aconst_null();
-            default:
-                push(0);
-            }
-        } else {
-            aconst_null();
-        }
-    }
-
-    /**
-     * Unboxes the object on the top of the stack. If the object is null, the
-     * unboxed primitive value becomes zero.
-     */
-    public void unbox_or_zero(Type type) {
-        if (TypeUtils.isPrimitive(type)) {
-            if (type != Type.VOID_TYPE) {
-                Label nonNull = make_label();
-                Label end = make_label();
-                dup();
-                ifnonnull(nonNull);
-                pop();
-                zero_or_null(type);
-                goTo(end);
-                mark(nonNull);
-                unbox(type);
-                mark(end);
-            }
-        } else {
-            checkcast(type);
-        }
-    }
-
-    public void visitMaxs(int maxStack, int maxLocals) {
-        if (!TypeUtils.isAbstract(state.access)) {
-            mv.visitMaxs(0, 0);
-        }
-    }
-
-    public void invoke(MethodInfo method, Type virtualType) {
-        ClassInfo classInfo = method.getClassInfo();
-        Type type = classInfo.getType();
-        Signature sig = method.getSignature();
-        if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
-            invoke_constructor(type, sig);
-        } else if (TypeUtils.isInterface(classInfo.getModifiers())) {
-            invoke_interface(type, sig);
-        } else if (TypeUtils.isStatic(method.getModifiers())) {
-            invoke_static(type, sig);
-        } else {
-            invoke_virtual(virtualType, sig);
-        }
-    }
-
-    public void invoke(MethodInfo method) {
-        invoke(method, method.getClassInfo().getType());
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/CodeGenerationException.java b/cglib-and-asm/src/org/mockito/cglib/core/CodeGenerationException.java
deleted file mode 100644
index 2fb46ff..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/CodeGenerationException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-/**
- * @version $Id: CodeGenerationException.java,v 1.3 2004/06/24 21:15:21 herbyderby Exp $
- */
-public class CodeGenerationException extends RuntimeException {
-    private Throwable cause;
-
-    public CodeGenerationException(Throwable cause) {
-        super(cause.getClass().getName() + "-->" + cause.getMessage());
-        this.cause = cause;
-    }
-
-    public Throwable getCause() {
-        return cause;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/CollectionUtils.java b/cglib-and-asm/src/org/mockito/cglib/core/CollectionUtils.java
deleted file mode 100644
index 97eeabe..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/CollectionUtils.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.util.*;
-import java.lang.reflect.Array;
-
-/**
- * @author Chris Nokleberg
- * @version $Id: CollectionUtils.java,v 1.7 2004/06/24 21:15:21 herbyderby Exp $
- */
-public class CollectionUtils {
-    private CollectionUtils() { }
-
-    public static Map bucket(Collection c, Transformer t) {
-        Map buckets = new HashMap();
-        for (Iterator it = c.iterator(); it.hasNext();) {
-            Object value = (Object)it.next();
-            Object key = t.transform(value);
-            List bucket = (List)buckets.get(key);
-            if (bucket == null) {
-                buckets.put(key, bucket = new LinkedList());
-            }
-            bucket.add(value);
-        }
-        return buckets;
-    }
-
-    public static void reverse(Map source, Map target) {
-        for (Iterator it = source.keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
-            target.put(source.get(key), key);
-        }
-    }
-
-    public static Collection filter(Collection c, Predicate p) {
-        Iterator it = c.iterator();
-        while (it.hasNext()) {
-            if (!p.evaluate(it.next())) {
-                it.remove();
-            }
-        }
-        return c;
-    }
-
-    public static List transform(Collection c, Transformer t) {
-        List result = new ArrayList(c.size());
-        for (Iterator it = c.iterator(); it.hasNext();) {
-            result.add(t.transform(it.next()));
-        }
-        return result;
-    }
-
-    public static Map getIndexMap(List list) {
-        Map indexes = new HashMap();
-        int index = 0;
-        for (Iterator it = list.iterator(); it.hasNext();) {
-            indexes.put(it.next(), new Integer(index++));
-        }
-        return indexes;
-    }
-}    
-    
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Constants.java b/cglib-and-asm/src/org/mockito/cglib/core/Constants.java
deleted file mode 100644
index 2336b2c..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Constants.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Type;
-
-/**
- * @author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">baliuka@mwm.lt</a>
- * @version $Id: Constants.java,v 1.21 2006/03/05 02:43:19 herbyderby Exp $
- */
-public interface Constants extends org.mockito.asm.Opcodes {
-    public static final Class[] EMPTY_CLASS_ARRAY = {};
-    public static final Type[] TYPES_EMPTY = {};
-
-    public static final Signature SIG_STATIC =
-      TypeUtils.parseSignature("void <clinit>()");
-    
-    public static final Type TYPE_OBJECT_ARRAY = TypeUtils.parseType("Object[]");
-    public static final Type TYPE_CLASS_ARRAY = TypeUtils.parseType("Class[]");
-    public static final Type TYPE_STRING_ARRAY = TypeUtils.parseType("String[]");
-
-    public static final Type TYPE_OBJECT = TypeUtils.parseType("Object");
-    public static final Type TYPE_CLASS = TypeUtils.parseType("Class");
-    public static final Type TYPE_CLASS_LOADER = TypeUtils.parseType("ClassLoader");
-    public static final Type TYPE_CHARACTER = TypeUtils.parseType("Character");
-    public static final Type TYPE_BOOLEAN = TypeUtils.parseType("Boolean");
-    public static final Type TYPE_DOUBLE = TypeUtils.parseType("Double");
-    public static final Type TYPE_FLOAT = TypeUtils.parseType("Float");
-    public static final Type TYPE_LONG = TypeUtils.parseType("Long");
-    public static final Type TYPE_INTEGER = TypeUtils.parseType("Integer");
-    public static final Type TYPE_SHORT = TypeUtils.parseType("Short");
-    public static final Type TYPE_BYTE = TypeUtils.parseType("Byte");
-    public static final Type TYPE_NUMBER = TypeUtils.parseType("Number");
-    public static final Type TYPE_STRING = TypeUtils.parseType("String");
-    public static final Type TYPE_THROWABLE = TypeUtils.parseType("Throwable");
-    public static final Type TYPE_BIG_INTEGER = TypeUtils.parseType("java.math.BigInteger");
-    public static final Type TYPE_BIG_DECIMAL = TypeUtils.parseType("java.math.BigDecimal");
-    public static final Type TYPE_STRING_BUFFER = TypeUtils.parseType("StringBuffer");
-    public static final Type TYPE_RUNTIME_EXCEPTION = TypeUtils.parseType("RuntimeException");
-    public static final Type TYPE_ERROR = TypeUtils.parseType("Error");
-    public static final Type TYPE_SYSTEM = TypeUtils.parseType("System");
-    public static final Type TYPE_SIGNATURE = TypeUtils.parseType("org.mockito.cglib.core.Signature");
-    
-    public static final String CONSTRUCTOR_NAME = "<init>";
-    public static final String STATIC_NAME = "<clinit>";
-    public static final String SOURCE_FILE = "<generated>";
-    public static final String SUID_FIELD_NAME = "serialVersionUID";
-
-    public static final int PRIVATE_FINAL_STATIC = ACC_PRIVATE | ACC_FINAL | ACC_STATIC;
-
-    public static final int SWITCH_STYLE_TRIE = 0;
-    public static final int SWITCH_STYLE_HASH = 1;
-    public static final int SWITCH_STYLE_HASHONLY = 2;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Converter.java b/cglib-and-asm/src/org/mockito/cglib/core/Converter.java
deleted file mode 100644
index 60c9687..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Converter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-public interface Converter {
-    Object convert(Object value, Class target, Object context);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Customizer.java b/cglib-and-asm/src/org/mockito/cglib/core/Customizer.java
deleted file mode 100644
index 15beba7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Customizer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Type;
-
-public interface Customizer {
-    void customize(CodeEmitter e, Type type);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/DebuggingClassWriter.java b/cglib-and-asm/src/org/mockito/cglib/core/DebuggingClassWriter.java
deleted file mode 100644
index 7c16440..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/DebuggingClassWriter.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.ClassReader;
-import org.mockito.asm.ClassWriter;
-import org.mockito.asm.util.TraceClassVisitor;
-
-import java.io.*;
-
-public class DebuggingClassWriter extends ClassWriter {
-    
-    public static final String DEBUG_LOCATION_PROPERTY = "cglib.debugLocation";
-    
-    private static String debugLocation;
-    private static boolean traceEnabled;
-    
-    private String className;
-    private String superName;
-    
-    static {
-        debugLocation = System.getProperty(DEBUG_LOCATION_PROPERTY);
-        if (debugLocation != null) {
-            System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");
-            try {
-                Class.forName("org.mockito.asm.util.TraceClassVisitor");
-                traceEnabled = true;
-            } catch (Throwable ignore) {
-            }
-        }
-    }
-    
-    public DebuggingClassWriter(int flags) {
-        super(flags);
-    }
-
-    public void visit(int version,
-                      int access,
-                      String name,
-                      String signature,
-                      String superName,
-                      String[] interfaces) {
-        className = name.replace('/', '.');
-        this.superName = superName.replace('/', '.');
-        super.visit(version, access, name, signature, superName, interfaces);
-    }
-    
-    public String getClassName() {
-        return className;
-    }
-    
-    public String getSuperName() {
-        return superName;
-    }
-    
-    public byte[] toByteArray() {
-        
-      return (byte[]) java.security.AccessController.doPrivileged(
-        new java.security.PrivilegedAction() {
-            public Object run() {
-                
-                
-                byte[] b = DebuggingClassWriter.super.toByteArray();
-                if (debugLocation != null) {
-                    String dirs = className.replace('.', File.separatorChar);
-                    try {
-                        new File(debugLocation + File.separatorChar + dirs).getParentFile().mkdirs();
-                        
-                        File file = new File(new File(debugLocation), dirs + ".class");
-                        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
-                        try {
-                            out.write(b);
-                        } finally {
-                            out.close();
-                        }
-                        
-                        if (traceEnabled) {
-                            file = new File(new File(debugLocation), dirs + ".asm");
-                            out = new BufferedOutputStream(new FileOutputStream(file));
-                            try {
-                                ClassReader cr = new ClassReader(b);
-                                PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
-                                TraceClassVisitor tcv = new TraceClassVisitor(null, pw);
-                                cr.accept(tcv, 0);
-                                pw.flush();
-                            } finally {
-                                out.close();
-                            }
-                        }
-                    } catch (IOException e) {
-                        throw new CodeGenerationException(e);
-                    }
-                }
-                return b;
-             }  
-            });
-            
-        }
-    }
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/DefaultGeneratorStrategy.java b/cglib-and-asm/src/org/mockito/cglib/core/DefaultGeneratorStrategy.java
deleted file mode 100644
index 55b52d8..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/DefaultGeneratorStrategy.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.ClassWriter;
-
-public class DefaultGeneratorStrategy implements GeneratorStrategy {
-    public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy();
-    
-    public byte[] generate(ClassGenerator cg) throws Exception {
-        ClassWriter cw = getClassWriter();
-        transform(cg).generateClass(cw);
-        return transform(cw.toByteArray());
-    }
-
-    protected ClassWriter getClassWriter() throws Exception {
-      return new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
-    }
-
-    protected byte[] transform(byte[] b) throws Exception {
-        return b;
-    }
-
-    protected ClassGenerator transform(ClassGenerator cg) throws Exception {
-        return cg;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/DefaultNamingPolicy.java b/cglib-and-asm/src/org/mockito/cglib/core/DefaultNamingPolicy.java
deleted file mode 100644
index a13f542..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/DefaultNamingPolicy.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.util.Set;
-
-/**
- * The default policy used by {@link AbstractClassGenerator}.
- * Generates names such as
- * <p><code>org.mockito.cglib.Foo$$EnhancerByCGLIB$$38272841</code><p>
- * This is composed of a prefix based on the name of the superclass, a fixed
- * string incorporating the CGLIB class responsible for generation, and a
- * hashcode derived from the parameters used to create the object. If the same
- * name has been previously been used in the same <code>ClassLoader</code>, a
- * suffix is added to ensure uniqueness.
- */
-public class DefaultNamingPolicy implements NamingPolicy {
-    public static final DefaultNamingPolicy INSTANCE = new DefaultNamingPolicy();
-    
-    public String getClassName(String prefix, String source, Object key, Predicate names) {
-        if (prefix == null) {
-            prefix = "org.mockito.cglib.empty.Object";
-        } else if (prefix.startsWith("java")) {
-            prefix = "$" + prefix;
-        }
-        String base =
-            prefix + "$$" + 
-            source.substring(source.lastIndexOf('.') + 1) +
-            getTag() + "$$" +
-            Integer.toHexString(key.hashCode());
-        String attempt = base;
-        int index = 2;
-        while (names.evaluate(attempt))
-            attempt = base + "_" + index++;
-        return attempt;
-    }
-
-    /**
-     * Returns a string which is incorporated into every generated class name.
-     * By default returns "ByCGLIB"
-     */
-    protected String getTag() {
-        return "ByCGLIB";
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/DuplicatesPredicate.java b/cglib-and-asm/src/org/mockito/cglib/core/DuplicatesPredicate.java
deleted file mode 100644
index ad46239..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/DuplicatesPredicate.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.lang.reflect.Method;
-import java.util.*;
-
-public class DuplicatesPredicate implements Predicate {
-    private Set unique = new HashSet();
-
-    public boolean evaluate(Object arg) {
-        return unique.add(MethodWrapper.create((Method)arg));
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/EmitUtils.java b/cglib-and-asm/src/org/mockito/cglib/core/EmitUtils.java
deleted file mode 100644
index 9cb67ad..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/EmitUtils.java
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.*;
-
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-
-public class EmitUtils {
-    private static final Signature CSTRUCT_NULL =
-      TypeUtils.parseConstructor("");
-    private static final Signature CSTRUCT_THROWABLE =
-      TypeUtils.parseConstructor("Throwable");
-
-    private static final Signature GET_NAME =
-      TypeUtils.parseSignature("String getName()");
-    private static final Signature HASH_CODE =
-      TypeUtils.parseSignature("int hashCode()");
-    private static final Signature EQUALS =
-      TypeUtils.parseSignature("boolean equals(Object)");
-    private static final Signature STRING_LENGTH =
-      TypeUtils.parseSignature("int length()");
-    private static final Signature STRING_CHAR_AT =
-      TypeUtils.parseSignature("char charAt(int)");
-    private static final Signature FOR_NAME =
-      TypeUtils.parseSignature("Class forName(String)");
-    private static final Signature DOUBLE_TO_LONG_BITS =
-      TypeUtils.parseSignature("long doubleToLongBits(double)");
-    private static final Signature FLOAT_TO_INT_BITS =
-      TypeUtils.parseSignature("int floatToIntBits(float)");
-    private static final Signature TO_STRING =
-      TypeUtils.parseSignature("String toString()");
-    private static final Signature APPEND_STRING =
-      TypeUtils.parseSignature("StringBuffer append(String)");
-    private static final Signature APPEND_INT =
-      TypeUtils.parseSignature("StringBuffer append(int)");
-    private static final Signature APPEND_DOUBLE =
-      TypeUtils.parseSignature("StringBuffer append(double)");
-    private static final Signature APPEND_FLOAT =
-      TypeUtils.parseSignature("StringBuffer append(float)");
-    private static final Signature APPEND_CHAR =
-      TypeUtils.parseSignature("StringBuffer append(char)");
-    private static final Signature APPEND_LONG =
-      TypeUtils.parseSignature("StringBuffer append(long)");
-    private static final Signature APPEND_BOOLEAN =
-      TypeUtils.parseSignature("StringBuffer append(boolean)");
-    private static final Signature LENGTH =
-      TypeUtils.parseSignature("int length()");
-    private static final Signature SET_LENGTH =
-      TypeUtils.parseSignature("void setLength(int)");
-    private static final Signature GET_DECLARED_METHOD =
-      TypeUtils.parseSignature("java.lang.reflect.Method getDeclaredMethod(String, Class[])");
-     
-    
-
-    public static final ArrayDelimiters DEFAULT_DELIMITERS = new ArrayDelimiters("{", ", ", "}");
-
-    private EmitUtils() {
-    }
-
-    public static void factory_method(ClassEmitter ce, Signature sig) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, sig, null);
-        e.new_instance_this();
-        e.dup();
-        e.load_args();
-        e.invoke_constructor_this(TypeUtils.parseConstructor(sig.getArgumentTypes()));
-        e.return_value();
-        e.end_method();
-    }
-
-    public static void null_constructor(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_NULL, null);
-        e.load_this();
-        e.super_invoke_constructor();
-        e.return_value();
-        e.end_method();
-    }
-    
-    /**
-     * Process an array on the stack. Assumes the top item on the stack
-     * is an array of the specified type. For each element in the array,
-     * puts the element on the stack and triggers the callback.
-     * @param type the type of the array (type.isArray() must be true)
-     * @param callback the callback triggered for each element
-     */
-    public static void process_array(CodeEmitter e, Type type, ProcessArrayCallback callback) {
-        Type componentType = TypeUtils.getComponentType(type);
-        Local array = e.make_local();
-        Local loopvar = e.make_local(Type.INT_TYPE);
-        Label loopbody = e.make_label();
-        Label checkloop = e.make_label();
-        e.store_local(array);
-        e.push(0);
-        e.store_local(loopvar);
-        e.goTo(checkloop);
-        
-        e.mark(loopbody);
-        e.load_local(array);
-        e.load_local(loopvar);
-        e.array_load(componentType);
-        callback.processElement(componentType);
-        e.iinc(loopvar, 1);
-        
-        e.mark(checkloop);
-        e.load_local(loopvar);
-        e.load_local(array);
-        e.arraylength();
-        e.if_icmp(e.LT, loopbody);
-    }
-    
-    /**
-     * Process two arrays on the stack in parallel. Assumes the top two items on the stack
-     * are arrays of the specified class. The arrays must be the same length. For each pair
-     * of elements in the arrays, puts the pair on the stack and triggers the callback.
-     * @param type the type of the arrays (type.isArray() must be true)
-     * @param callback the callback triggered for each pair of elements
-     */
-    public static void process_arrays(CodeEmitter e, Type type, ProcessArrayCallback callback) {
-        Type componentType = TypeUtils.getComponentType(type);
-        Local array1 = e.make_local();
-        Local array2 = e.make_local();
-        Local loopvar = e.make_local(Type.INT_TYPE);
-        Label loopbody = e.make_label();
-        Label checkloop = e.make_label();
-        e.store_local(array1);
-        e.store_local(array2);
-        e.push(0);
-        e.store_local(loopvar);
-        e.goTo(checkloop);
-        
-        e.mark(loopbody);
-        e.load_local(array1);
-        e.load_local(loopvar);
-        e.array_load(componentType);
-        e.load_local(array2);
-        e.load_local(loopvar);
-        e.array_load(componentType);
-        callback.processElement(componentType);
-        e.iinc(loopvar, 1);
-        
-        e.mark(checkloop);
-        e.load_local(loopvar);
-        e.load_local(array1);
-        e.arraylength();
-        e.if_icmp(e.LT, loopbody);
-    }
-    
-    public static void string_switch(CodeEmitter e, String[] strings, int switchStyle, ObjectSwitchCallback callback) {
-        try {
-            switch (switchStyle) {
-            case Constants.SWITCH_STYLE_TRIE:
-                string_switch_trie(e, strings, callback);
-                break;
-            case Constants.SWITCH_STYLE_HASH:
-                string_switch_hash(e, strings, callback, false);
-                break;
-            case Constants.SWITCH_STYLE_HASHONLY:
-                string_switch_hash(e, strings, callback, true);
-                break;
-            default:
-                throw new IllegalArgumentException("unknown switch style " + switchStyle);
-            }
-        } catch (RuntimeException ex) {
-            throw ex;
-        } catch (Error ex) {
-            throw ex;
-        } catch (Exception ex) {
-            throw new CodeGenerationException(ex);
-        }
-    }
-
-    private static void string_switch_trie(final CodeEmitter e,
-                                           String[] strings,
-                                           final ObjectSwitchCallback callback) throws Exception {
-        final Label def = e.make_label();
-        final Label end = e.make_label();
-        final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() {
-            public Object transform(Object value) {
-                return new Integer(((String)value).length());
-            }
-        });
-        e.dup();
-        e.invoke_virtual(Constants.TYPE_STRING, STRING_LENGTH);
-        e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() {
-                public void processCase(int key, Label ignore_end) throws Exception {
-                    List bucket = (List)buckets.get(new Integer(key));
-                    stringSwitchHelper(e, bucket, callback, def, end, 0);
-                }
-                public void processDefault() {
-                    e.goTo(def);
-                }
-            });
-        e.mark(def);
-        e.pop();
-        callback.processDefault();
-        e.mark(end);
-    }
-
-    private static void stringSwitchHelper(final CodeEmitter e,
-                                           List strings,
-                                           final ObjectSwitchCallback callback,
-                                           final Label def,
-                                           final Label end,
-                                           final int index) throws Exception {
-        final int len = ((String)strings.get(0)).length();
-        final Map buckets = CollectionUtils.bucket(strings, new Transformer() {
-            public Object transform(Object value) {
-                return new Integer(((String)value).charAt(index));
-            }
-        });
-        e.dup();
-        e.push(index);
-        e.invoke_virtual(Constants.TYPE_STRING, STRING_CHAR_AT);
-        e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() {
-                public void processCase(int key, Label ignore_end) throws Exception {
-                    List bucket = (List)buckets.get(new Integer(key));
-                    if (index + 1 == len) {
-                        e.pop();
-                        callback.processCase(bucket.get(0), end);
-                    } else {
-                        stringSwitchHelper(e, bucket, callback, def, end, index + 1);
-                    }
-                }
-                public void processDefault() {
-                    e.goTo(def);
-                }
-            });
-    }        
-
-    static int[] getSwitchKeys(Map buckets) {
-        int[] keys = new int[buckets.size()];
-        int index = 0;
-        for (Iterator it = buckets.keySet().iterator(); it.hasNext();) {
-            keys[index++] = ((Integer)it.next()).intValue();
-        }
-        Arrays.sort(keys);
-        return keys;
-    }
-
-    private static void string_switch_hash(final CodeEmitter e,
-                                           final String[] strings,
-                                           final ObjectSwitchCallback callback,
-                                           final boolean skipEquals) throws Exception {
-        final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() {
-            public Object transform(Object value) {
-                return new Integer(value.hashCode());
-            }
-        });
-        final Label def = e.make_label();
-        final Label end = e.make_label();
-        e.dup();
-        e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE);
-        e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() {
-            public void processCase(int key, Label ignore_end) throws Exception {
-                List bucket = (List)buckets.get(new Integer(key));
-                Label next = null;
-                if (skipEquals && bucket.size() == 1) {
-                    if (skipEquals)
-                        e.pop();
-                    callback.processCase((String)bucket.get(0), end);
-                } else {
-                    for (Iterator it = bucket.iterator(); it.hasNext();) {
-                        String string = (String)it.next();
-                        if (next != null) {
-                            e.mark(next);
-                        }
-                        if (it.hasNext()) {
-                            e.dup();
-                        }
-                        e.push(string);
-                        e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS);
-                        if (it.hasNext()) {
-                            e.if_jump(e.EQ, next = e.make_label());
-                            e.pop();
-                        } else {
-                            e.if_jump(e.EQ, def);
-                        }
-                        callback.processCase(string, end);
-                    }
-                }
-            }
-            public void processDefault() {
-                e.pop();
-            }
-        });
-        e.mark(def);
-        callback.processDefault();
-        e.mark(end);
-    }
-
-    public static void load_class_this(CodeEmitter e) {
-        load_class_helper(e, e.getClassEmitter().getClassType());
-    }
-    
-    public static void load_class(CodeEmitter e, Type type) {
-        if (TypeUtils.isPrimitive(type)) {
-            if (type == Type.VOID_TYPE) {
-                throw new IllegalArgumentException("cannot load void type");
-            }
-            e.getstatic(TypeUtils.getBoxedType(type), "TYPE", Constants.TYPE_CLASS);
-        } else {
-            load_class_helper(e, type);
-        }
-    }
-
-    private static void load_class_helper(CodeEmitter e, final Type type) {
-        if (e.isStaticHook()) {
-            // have to fall back on non-optimized load
-            e.push(TypeUtils.emulateClassGetName(type));
-            e.invoke_static(Constants.TYPE_CLASS, FOR_NAME);
-        } else {
-            ClassEmitter ce = e.getClassEmitter();
-            String typeName = TypeUtils.emulateClassGetName(type);
-
-            // TODO: can end up with duplicated field names when using chained transformers; incorporate static hook # somehow
-            String fieldName = "CGLIB$load_class$" + TypeUtils.escapeType(typeName);
-            if (!ce.isFieldDeclared(fieldName)) {
-                ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, Constants.TYPE_CLASS, null);
-                CodeEmitter hook = ce.getStaticHook();
-                hook.push(typeName);
-                hook.invoke_static(Constants.TYPE_CLASS, FOR_NAME);
-                hook.putstatic(ce.getClassType(), fieldName, Constants.TYPE_CLASS);
-            }
-            e.getfield(fieldName);
-        }
-    }
-
-    public static void push_array(CodeEmitter e, Object[] array) {
-        e.push(array.length);
-        e.newarray(Type.getType(remapComponentType(array.getClass().getComponentType())));
-        for (int i = 0; i < array.length; i++) {
-            e.dup();
-            e.push(i);
-            push_object(e, array[i]);
-            e.aastore();
-        }
-    }
-
-    private static Class remapComponentType(Class componentType) {
-        if (componentType.equals(Type.class))
-            return Class.class;
-        return componentType;
-    }
-    
-    public static void push_object(CodeEmitter e, Object obj) {
-        if (obj == null) {
-            e.aconst_null();
-        } else {
-            Class type = obj.getClass();
-            if (type.isArray()) {
-                push_array(e, (Object[])obj);
-            } else if (obj instanceof String) {
-                e.push((String)obj);
-            } else if (obj instanceof Type) {
-                load_class(e, (Type)obj);
-            } else if (obj instanceof Class) {
-                load_class(e, Type.getType((Class)obj));
-            } else if (obj instanceof BigInteger) {
-                e.new_instance(Constants.TYPE_BIG_INTEGER);
-                e.dup();
-                e.push(obj.toString());
-                e.invoke_constructor(Constants.TYPE_BIG_INTEGER);
-            } else if (obj instanceof BigDecimal) {
-                e.new_instance(Constants.TYPE_BIG_DECIMAL);
-                e.dup();
-                e.push(obj.toString());
-                e.invoke_constructor(Constants.TYPE_BIG_DECIMAL);
-            } else {
-                throw new IllegalArgumentException("unknown type: " + obj.getClass());
-            }
-        }
-    }
-
-    public static void hash_code(CodeEmitter e, Type type, int multiplier, Customizer customizer) {
-        if (TypeUtils.isArray(type)) {
-            hash_array(e, type, multiplier, customizer);
-        } else {
-            e.swap(Type.INT_TYPE, type);
-            e.push(multiplier);
-            e.math(e.MUL, Type.INT_TYPE);
-            e.swap(type, Type.INT_TYPE);
-            if (TypeUtils.isPrimitive(type)) {
-                hash_primitive(e, type);
-            } else {
-                hash_object(e, type, customizer);
-            }
-            e.math(e.ADD, Type.INT_TYPE);
-        }
-    }
-
-    private static void hash_array(final CodeEmitter e, Type type, final int multiplier, final Customizer customizer) {
-        Label skip = e.make_label();
-        Label end = e.make_label();
-        e.dup();
-        e.ifnull(skip);
-        EmitUtils.process_array(e, type, new ProcessArrayCallback() {
-            public void processElement(Type type) {
-                hash_code(e, type, multiplier, customizer);
-            }
-        });
-        e.goTo(end);
-        e.mark(skip);
-        e.pop();
-        e.mark(end);
-    }
-
-    private static void hash_object(CodeEmitter e, Type type, Customizer customizer) {
-        // (f == null) ? 0 : f.hashCode();
-        Label skip = e.make_label();
-        Label end = e.make_label();
-        e.dup();
-        e.ifnull(skip);
-        if (customizer != null) {
-            customizer.customize(e, type);
-        }
-        e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE);
-        e.goTo(end);
-        e.mark(skip);
-        e.pop();
-        e.push(0);
-        e.mark(end);
-    }
-
-    private static void hash_primitive(CodeEmitter e, Type type) {
-        switch (type.getSort()) {
-        case Type.BOOLEAN:
-            // f ? 0 : 1
-            e.push(1);
-            e.math(e.XOR, Type.INT_TYPE);
-            break;
-        case Type.FLOAT:
-            // Float.floatToIntBits(f)
-            e.invoke_static(Constants.TYPE_FLOAT, FLOAT_TO_INT_BITS);
-            break;
-        case Type.DOUBLE:
-            // Double.doubleToLongBits(f), hash_code(Long.TYPE)
-            e.invoke_static(Constants.TYPE_DOUBLE, DOUBLE_TO_LONG_BITS);
-            // fall through
-        case Type.LONG:
-            hash_long(e);
-        }
-    }
-
-    private static void hash_long(CodeEmitter e) {
-        // (int)(f ^ (f >>> 32))
-        e.dup2();
-        e.push(32);
-        e.math(e.USHR, Type.LONG_TYPE);
-        e.math(e.XOR, Type.LONG_TYPE);
-        e.cast_numeric(Type.LONG_TYPE, Type.INT_TYPE);
-    }
-
-//     public static void not_equals(CodeEmitter e, Type type, Label notEquals) {
-//         not_equals(e, type, notEquals, null);
-//     }
-    
-    /**
-     * Branches to the specified label if the top two items on the stack
-     * are not equal. The items must both be of the specified
-     * class. Equality is determined by comparing primitive values
-     * directly and by invoking the <code>equals</code> method for
-     * Objects. Arrays are recursively processed in the same manner.
-     */
-    public static void not_equals(final CodeEmitter e, Type type, final Label notEquals, final Customizer customizer) {
-        (new ProcessArrayCallback() {
-            public void processElement(Type type) {
-                not_equals_helper(e, type, notEquals, customizer, this);
-            }
-        }).processElement(type);
-    }
-    
-    private static void not_equals_helper(CodeEmitter e,
-                                          Type type,
-                                          Label notEquals,
-                                          Customizer customizer,
-                                          ProcessArrayCallback callback) {
-        if (TypeUtils.isPrimitive(type)) {
-            e.if_cmp(type, e.NE, notEquals);
-        } else {
-            Label end = e.make_label();
-            nullcmp(e, notEquals, end);
-            if (TypeUtils.isArray(type)) {
-                Label checkContents = e.make_label();
-                e.dup2();
-                e.arraylength();
-                e.swap();
-                e.arraylength();
-                e.if_icmp(e.EQ, checkContents);
-                e.pop2();
-                e.goTo(notEquals);
-                e.mark(checkContents);
-                EmitUtils.process_arrays(e, type, callback);
-            } else {
-                if (customizer != null) {
-                    customizer.customize(e, type);
-                    e.swap();
-                    customizer.customize(e, type);
-                }
-                e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS);
-                e.if_jump(e.EQ, notEquals);
-            }
-            e.mark(end);
-        }
-    }
-
-    /**
-     * If both objects on the top of the stack are non-null, does nothing.
-     * If one is null, or both are null, both are popped off and execution
-     * branches to the respective label.
-     * @param oneNull label to branch to if only one of the objects is null
-     * @param bothNull label to branch to if both of the objects are null
-     */
-    private static void nullcmp(CodeEmitter e, Label oneNull, Label bothNull) {
-        e.dup2();
-        Label nonNull = e.make_label();
-        Label oneNullHelper = e.make_label();
-        Label end = e.make_label();
-        e.ifnonnull(nonNull);
-        e.ifnonnull(oneNullHelper);
-        e.pop2();
-        e.goTo(bothNull);
-        
-        e.mark(nonNull);
-        e.ifnull(oneNullHelper);
-        e.goTo(end);
-        
-        e.mark(oneNullHelper);
-        e.pop2();
-        e.goTo(oneNull);
-        
-        e.mark(end);
-    }
-
-    /*
-    public static void to_string(CodeEmitter e,
-                                 Type type,
-                                 ArrayDelimiters delims,
-                                 Customizer customizer) {
-        e.new_instance(Constants.TYPE_STRING_BUFFER);
-        e.dup();
-        e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
-        e.swap();
-        append_string(e, type, delims, customizer);
-        e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
-    }
-    */
-
-    public static void append_string(final CodeEmitter e,
-                                     Type type,
-                                     final ArrayDelimiters delims,
-                                     final Customizer customizer) {
-        final ArrayDelimiters d = (delims != null) ? delims : DEFAULT_DELIMITERS;
-        ProcessArrayCallback callback = new ProcessArrayCallback() {
-            public void processElement(Type type) {
-                append_string_helper(e, type, d, customizer, this);
-                e.push(d.inside);
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
-            }
-        };
-        append_string_helper(e, type, d, customizer, callback);
-    }
-
-    private static void append_string_helper(CodeEmitter e,
-                                             Type type,
-                                             ArrayDelimiters delims,
-                                             Customizer customizer,
-                                             ProcessArrayCallback callback) {
-        Label skip = e.make_label();
-        Label end = e.make_label();
-        if (TypeUtils.isPrimitive(type)) {
-            switch (type.getSort()) {
-            case Type.INT:
-            case Type.SHORT:
-            case Type.BYTE:
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_INT);
-                break;
-            case Type.DOUBLE:
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_DOUBLE);
-                break;
-            case Type.FLOAT:
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_FLOAT);
-                break;
-            case Type.LONG:
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_LONG);
-                break;
-            case Type.BOOLEAN:
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_BOOLEAN);
-                break;
-            case Type.CHAR:
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_CHAR);
-                break;
-            }
-        } else if (TypeUtils.isArray(type)) {
-            e.dup();
-            e.ifnull(skip);
-            e.swap();
-            if (delims != null && delims.before != null && !"".equals(delims.before)) {
-                e.push(delims.before);
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
-                e.swap();
-            }
-            EmitUtils.process_array(e, type, callback);
-            shrinkStringBuffer(e, 2);
-            if (delims != null && delims.after != null && !"".equals(delims.after)) {
-                e.push(delims.after);
-                e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
-            }
-        } else {
-            e.dup();
-            e.ifnull(skip);
-            if (customizer != null) {
-                customizer.customize(e, type);
-            }
-            e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
-            e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
-        }
-        e.goTo(end);
-        e.mark(skip);
-        e.pop();
-        e.push("null");
-        e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
-        e.mark(end);
-    }
-
-    private static void shrinkStringBuffer(CodeEmitter e, int amt) {
-        e.dup();
-        e.dup();
-        e.invoke_virtual(Constants.TYPE_STRING_BUFFER, LENGTH);
-        e.push(amt);
-        e.math(e.SUB, Type.INT_TYPE);
-        e.invoke_virtual(Constants.TYPE_STRING_BUFFER, SET_LENGTH);
-    }
-
-    public static class ArrayDelimiters {
-        private String before;
-        private String inside;
-        private String after;
-            
-        public ArrayDelimiters(String before, String inside, String after) {
-            this.before = before;
-            this.inside = inside;
-            this.after = after;
-        }
-    }
-
-    public static void load_method(CodeEmitter e, MethodInfo method) {
-        load_class(e, method.getClassInfo().getType());
-        e.push(method.getSignature().getName());
-        push_object(e, method.getSignature().getArgumentTypes());
-        e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHOD);
-    }
-
-    private interface ParameterTyper {
-        Type[] getParameterTypes(MethodInfo member);
-    }
-
-    public static void method_switch(CodeEmitter e,
-                                     List methods,
-                                     ObjectSwitchCallback callback) {
-        member_switch_helper(e, methods, callback, true);
-    }
-
-    public static void constructor_switch(CodeEmitter e,
-                                          List constructors,
-                                          ObjectSwitchCallback callback) {
-        member_switch_helper(e, constructors, callback, false);
-    }
-
-    private static void member_switch_helper(final CodeEmitter e,
-                                             List members,
-                                             final ObjectSwitchCallback callback,
-                                             boolean useName) {
-        try {
-            final Map cache = new HashMap();
-            final ParameterTyper cached = new ParameterTyper() {
-                    public Type[] getParameterTypes(MethodInfo member) {
-                        Type[] types = (Type[])cache.get(member);
-                        if (types == null) {
-                            cache.put(member, types = member.getSignature().getArgumentTypes());
-                        }
-                        return types;
-                    }
-                };
-            final Label def = e.make_label();
-            final Label end = e.make_label();
-            if (useName) {
-                e.swap();
-                final Map buckets = CollectionUtils.bucket(members, new Transformer() {
-                        public Object transform(Object value) {
-                            return ((MethodInfo)value).getSignature().getName();
-                        }
-                    });
-                String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]);
-                EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-                        public void processCase(Object key, Label dontUseEnd) throws Exception {
-                            member_helper_size(e, (List)buckets.get(key), callback, cached, def, end);
-                        }
-                        public void processDefault() throws Exception {
-                            e.goTo(def);
-                        }
-                    });
-            } else {
-                member_helper_size(e, members, callback, cached, def, end);
-            }
-            e.mark(def);
-            e.pop();
-            callback.processDefault();
-            e.mark(end);
-        } catch (RuntimeException ex) {
-            throw ex;
-        } catch (Error ex) {
-            throw ex;
-        } catch (Exception ex) {
-            throw new CodeGenerationException(ex);
-        }
-    }
-
-    private static void member_helper_size(final CodeEmitter e,
-                                           List members,
-                                           final ObjectSwitchCallback callback,
-                                           final ParameterTyper typer,
-                                           final Label def,
-                                           final Label end) throws Exception {
-        final Map buckets = CollectionUtils.bucket(members, new Transformer() {
-            public Object transform(Object value) {
-                return new Integer(typer.getParameterTypes((MethodInfo)value).length);
-            }
-        });
-        e.dup();
-        e.arraylength();
-        e.process_switch(EmitUtils.getSwitchKeys(buckets), new ProcessSwitchCallback() {
-            public void processCase(int key, Label dontUseEnd) throws Exception {
-                List bucket = (List)buckets.get(new Integer(key));
-                member_helper_type(e, bucket, callback, typer, def, end, new BitSet());
-            }
-            public void processDefault() throws Exception {
-                e.goTo(def);
-            }
-        });
-    }
-
-    private static void member_helper_type(final CodeEmitter e,
-                                           List members,
-                                           final ObjectSwitchCallback callback,
-                                           final ParameterTyper typer,
-                                           final Label def,
-                                           final Label end,
-                                           final BitSet checked) throws Exception {
-        if (members.size() == 1) {
-            MethodInfo member = (MethodInfo)members.get(0);
-            Type[] types = typer.getParameterTypes(member);
-            // need to check classes that have not already been checked via switches
-            for (int i = 0; i < types.length; i++) {
-                if (checked == null || !checked.get(i)) {
-                    e.dup();
-                    e.aaload(i);
-                    e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME);
-                    e.push(TypeUtils.emulateClassGetName(types[i]));
-                    e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS);
-                    e.if_jump(e.EQ, def);
-                }
-            }
-            e.pop();
-            callback.processCase(member, end);
-        } else {
-            // choose the index that has the best chance of uniquely identifying member
-            Type[] example = typer.getParameterTypes((MethodInfo)members.get(0));
-            Map buckets = null;
-            int index = -1;
-            for (int i = 0; i < example.length; i++) {
-                final int j = i;
-                Map test = CollectionUtils.bucket(members, new Transformer() {
-                    public Object transform(Object value) {
-                        return TypeUtils.emulateClassGetName(typer.getParameterTypes((MethodInfo)value)[j]);
-                    }
-                });
-                if (buckets == null || test.size() > buckets.size()) {
-                    buckets = test;
-                    index = i;
-                }
-            }
-            if (buckets == null || buckets.size() == 1) {
-                // TODO: switch by returnType
-                // must have two methods with same name, types, and different return types
-                e.goTo(def);
-            } else {
-                checked.set(index);
-
-                e.dup();
-                e.aaload(index);
-                e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME);
-
-                final Map fbuckets = buckets;
-                String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]);
-                EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-                    public void processCase(Object key, Label dontUseEnd) throws Exception {
-                        member_helper_type(e, (List)fbuckets.get(key), callback, typer, def, end, checked);
-                    }
-                    public void processDefault() throws Exception {
-                        e.goTo(def);
-                    }
-                });
-            }
-        }
-    }
-
-    public static void wrap_throwable(Block block, Type wrapper) {
-        CodeEmitter e = block.getCodeEmitter();
-        e.catch_exception(block, Constants.TYPE_THROWABLE);
-        e.new_instance(wrapper);
-        e.dup_x1();
-        e.swap();
-        e.invoke_constructor(wrapper, CSTRUCT_THROWABLE);
-        e.athrow();
-    }
-
-    public static void add_properties(ClassEmitter ce, String[] names, Type[] types) {
-        for (int i = 0; i < names.length; i++) {
-            String fieldName = "$cglib_prop_" + names[i];
-            ce.declare_field(Constants.ACC_PRIVATE, fieldName, types[i], null);
-            EmitUtils.add_property(ce, names[i], types[i], fieldName);
-        }
-    }
-
-    public static void add_property(ClassEmitter ce, String name, Type type, String fieldName) {
-        String property = TypeUtils.upperFirst(name);
-        CodeEmitter e;
-        e = ce.begin_method(Constants.ACC_PUBLIC,
-                            new Signature("get" + property,
-                                          type,
-                                          Constants.TYPES_EMPTY),
-                            null);
-        e.load_this();
-        e.getfield(fieldName);
-        e.return_value();
-        e.end_method();
-
-        e = ce.begin_method(Constants.ACC_PUBLIC,
-                            new Signature("set" + property,
-                                          Type.VOID_TYPE,
-                                          new Type[]{ type }),
-                            null);
-        e.load_this();
-        e.load_arg(0);
-        e.putfield(fieldName);
-        e.return_value();
-        e.end_method();
-    }
-
-    /* generates:
-       } catch (RuntimeException e) {
-         throw e;
-       } catch (Error e) {
-         throw e;
-       } catch (<DeclaredException> e) {
-         throw e;
-       } catch (Throwable e) {
-         throw new <Wrapper>(e);
-       }
-    */
-    public static void wrap_undeclared_throwable(CodeEmitter e, Block handler, Type[] exceptions, Type wrapper) {
-        Set set = (exceptions == null) ? Collections.EMPTY_SET : new HashSet(Arrays.asList(exceptions));
-
-        if (set.contains(Constants.TYPE_THROWABLE))
-            return;
-
-        boolean needThrow = exceptions != null;
-        if (!set.contains(Constants.TYPE_RUNTIME_EXCEPTION)) {
-            e.catch_exception(handler, Constants.TYPE_RUNTIME_EXCEPTION);
-            needThrow = true;
-        }
-        if (!set.contains(Constants.TYPE_ERROR)) {
-            e.catch_exception(handler, Constants.TYPE_ERROR);
-            needThrow = true;
-        }
-        if (exceptions != null) {
-            for (int i = 0; i < exceptions.length; i++) {
-                e.catch_exception(handler, exceptions[i]);
-            }
-        }
-        if (needThrow) {
-            e.athrow();
-        }
-        // e -> eo -> oeo -> ooe -> o
-        e.catch_exception(handler, Constants.TYPE_THROWABLE);
-        e.new_instance(wrapper);
-        e.dup_x1();
-        e.swap();
-        e.invoke_constructor(wrapper, CSTRUCT_THROWABLE);
-        e.athrow();
-    }
-
-    public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method) {
-        return begin_method(e, method, method.getModifiers());
-    }
-
-    public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method, int access) {
-        return e.begin_method(access,
-                              method.getSignature(),
-                              method.getExceptionTypes());
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/GeneratorStrategy.java b/cglib-and-asm/src/org/mockito/cglib/core/GeneratorStrategy.java
deleted file mode 100644
index dee3773..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/GeneratorStrategy.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-/**
- * The <code>GeneratorStrategy</code. is responsible for taking a
- * {@link ClassGenerator} and producing a byte array containing the
- * data for the generated <code>Class</code>.  By providing your
- * own strategy you may examine or modify the generated class before
- * it is loaded. Typically this will be accomplished by subclassing
- * {@link DefaultGeneratorStrategy} and overriding the appropriate
- * protected method.
- * @see AbstractClassGenerator#setStrategy
- */
-public interface GeneratorStrategy {
-    /**
-     * Generate the class.
-     * @param cg a class generator on which you can call {@link ClassGenerator#generateClass}
-     * @return a byte array containing the bits of a valid Class
-     */
-    byte[] generate(ClassGenerator cg) throws Exception;
-
-    /**
-     * The <code>GeneratorStrategy</code> in use does not currently, but may
-     * in the future, affect the caching of classes generated by {@link
-     * AbstractClassGenerator}, so this is a reminder that you should
-     * correctly implement <code>equals</code> and <code>hashCode</code>
-     * to avoid generating too many classes.
-     */
-    boolean equals(Object o);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/KeyFactory.java b/cglib-and-asm/src/org/mockito/cglib/core/KeyFactory.java
deleted file mode 100644
index e0f5ab5..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/KeyFactory.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.mockito.cglib.core;
-
-import java.lang.reflect.Method;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-
-/**
- * Generates classes to handle multi-valued keys, for use in things such as Maps and Sets.
- * Code for <code>equals</code> and <code>hashCode</code> methods follow the
- * the rules laid out in <i>Effective Java</i> by Joshua Bloch. 
- * <p>
- * To generate a <code>KeyFactory</code>, you need to supply an interface which
- * describes the structure of the key. The interface should have a
- * single method named <code>newInstance</code>, which returns an
- * <code>Object</code>. The arguments array can be
- * <i>anything</i>--Objects, primitive values, or single or
- * multi-dimension arrays of either. For example:
- * <p><pre>
- *     private interface IntStringKey {
- *         public Object newInstance(int i, String s);
- *     }
- * </pre><p>
- * Once you have made a <code>KeyFactory</code>, you generate a new key by calling
- * the <code>newInstance</code> method defined by your interface.
- * <p><pre>
- *     IntStringKey factory = (IntStringKey)KeyFactory.create(IntStringKey.class);
- *     Object key1 = factory.newInstance(4, "Hello");
- *     Object key2 = factory.newInstance(4, "World");
- * </pre><p>
- * <b>Note:</b>
- * <code>hashCode</code> equality between two keys <code>key1</code> and <code>key2</code> is only guaranteed if
- * <code>key1.equals(key2)</code> <i>and</i> the keys were produced by the same factory.
- *
- * @version $Id: KeyFactory.java,v 1.26 2006/03/05 02:43:19 herbyderby Exp $
- */
-abstract public class KeyFactory {
-    private static final Signature GET_NAME =
-      TypeUtils.parseSignature("String getName()");
-    private static final Signature GET_CLASS =
-      TypeUtils.parseSignature("Class getClass()");
-    private static final Signature HASH_CODE =
-      TypeUtils.parseSignature("int hashCode()");
-    private static final Signature EQUALS =
-      TypeUtils.parseSignature("boolean equals(Object)");
-    private static final Signature TO_STRING =
-      TypeUtils.parseSignature("String toString()");
-    private static final Signature APPEND_STRING =
-      TypeUtils.parseSignature("StringBuffer append(String)");
-    private static final Type KEY_FACTORY =
-      TypeUtils.parseType("org.mockito.cglib.core.KeyFactory");
-    
-    //generated numbers: 
-    private final static int PRIMES[] = {
-               11,         73,        179,       331,
-              521,        787,       1213,      1823,
-             2609,       3691,       5189,      7247,
-            10037,      13931,      19289,     26627,
-            36683,      50441,      69403,     95401,
-           131129,     180179,     247501,    340057,
-           467063,     641371,     880603,   1209107,
-          1660097,    2279161,    3129011,   4295723,
-          5897291,    8095873,   11114263,  15257791,
-         20946017,   28754629,   39474179,  54189869,
-         74391461,  102123817,  140194277, 192456917,
-        264202273,  362693231,  497900099, 683510293,
-        938313161, 1288102441, 1768288259  };
-    
-
-    public static final Customizer CLASS_BY_NAME = new Customizer() {
-        public void customize(CodeEmitter e, Type type) {
-            if (type.equals(Constants.TYPE_CLASS)) {
-                e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME);
-            }
-        }
-    };
-
-    public static final Customizer OBJECT_BY_CLASS = new Customizer() {
-        public void customize(CodeEmitter e, Type type) {
-            e.invoke_virtual(Constants.TYPE_OBJECT, GET_CLASS);
-        }
-    };
-
-    protected KeyFactory() {
-    }
-
-    public static KeyFactory create(Class keyInterface) {
-        return create(keyInterface, null);
-    }
-
-    public static KeyFactory create(Class keyInterface, Customizer customizer) {
-        return create(keyInterface.getClassLoader(), keyInterface,  customizer);
-    }
-
-    public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
-        Generator gen = new Generator();
-        gen.setInterface(keyInterface);
-        gen.setCustomizer(customizer);
-        gen.setClassLoader(loader);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(KeyFactory.class.getName());
-        private Class keyInterface;
-        private Customizer customizer;
-        private int constant;
-        private int multiplier;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return keyInterface.getClassLoader();
-        }
-
-        public void setCustomizer(Customizer customizer) {
-            this.customizer = customizer;
-        }
-
-        public void setInterface(Class keyInterface) {
-            this.keyInterface = keyInterface;
-        }
-
-        public KeyFactory create() {
-            setNamePrefix(keyInterface.getName());
-            return (KeyFactory)super.create(keyInterface.getName());
-        }
-
-        public void setHashConstant(int constant) {
-            this.constant = constant;
-        }
-
-        public void setHashMultiplier(int multiplier) {
-            this.multiplier = multiplier;
-        }
-
-        protected Object firstInstance(Class type) {
-            return ReflectUtils.newInstance(type);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return instance;
-        }
-
-        public void generateClass(ClassVisitor v) {
-            ClassEmitter ce = new ClassEmitter(v);
-            
-            Method newInstance = ReflectUtils.findNewInstance(keyInterface);
-            if (!newInstance.getReturnType().equals(Object.class)) {
-                throw new IllegalArgumentException("newInstance method must return Object");
-            }
-
-            Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           KEY_FACTORY,
-                           new Type[]{ Type.getType(keyInterface) },
-                           Constants.SOURCE_FILE);
-            EmitUtils.null_constructor(ce);
-            EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
-
-            int seed = 0;
-            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
-                                            TypeUtils.parseConstructor(parameterTypes),
-                                            null);
-            e.load_this();
-            e.super_invoke_constructor();
-            e.load_this();
-            for (int i = 0; i < parameterTypes.length; i++) {
-                seed += parameterTypes[i].hashCode();
-                ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL,
-                                 getFieldName(i),
-                                 parameterTypes[i],
-                                 null);
-                e.dup();
-                e.load_arg(i);
-                e.putfield(getFieldName(i));
-            }
-            e.return_value();
-            e.end_method();
-            
-            // hash code
-            e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
-            int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)];
-            int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)];
-            e.push(hc);
-            for (int i = 0; i < parameterTypes.length; i++) {
-                e.load_this();
-                e.getfield(getFieldName(i));
-                EmitUtils.hash_code(e, parameterTypes[i], hm, customizer);
-            }
-            e.return_value();
-            e.end_method();
-
-            // equals
-            e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null);
-            Label fail = e.make_label();
-            e.load_arg(0);
-            e.instance_of_this();
-            e.if_jump(e.EQ, fail);
-            for (int i = 0; i < parameterTypes.length; i++) {
-                e.load_this();
-                e.getfield(getFieldName(i));
-                e.load_arg(0);
-                e.checkcast_this();
-                e.getfield(getFieldName(i));
-                EmitUtils.not_equals(e, parameterTypes[i], fail, customizer);
-            }
-            e.push(1);
-            e.return_value();
-            e.mark(fail);
-            e.push(0);
-            e.return_value();
-            e.end_method();
-
-            // toString
-            e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null);
-            e.new_instance(Constants.TYPE_STRING_BUFFER);
-            e.dup();
-            e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
-            for (int i = 0; i < parameterTypes.length; i++) {
-                if (i > 0) {
-                    e.push(", ");
-                    e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
-                }
-                e.load_this();
-                e.getfield(getFieldName(i));
-                EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizer);
-            }
-            e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
-            e.return_value();
-            e.end_method();
-
-            ce.end_class();
-        }
-
-        private String getFieldName(int arg) {
-            return "FIELD_" + arg;
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Local.java b/cglib-and-asm/src/org/mockito/cglib/core/Local.java
deleted file mode 100644
index 55e815b..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Local.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Type;
-
-public class Local
-{
-    private Type type;
-    private int index;
-    
-    public Local(int index, Type type) {
-        this.type = type;
-        this.index = index;
-    }
-    
-    public int getIndex() {
-        return index;
-    }
-
-    public Type getType() {
-        return type;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/LocalVariablesSorter.java b/cglib-and-asm/src/org/mockito/cglib/core/LocalVariablesSorter.java
deleted file mode 100644
index 1daff06..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/LocalVariablesSorter.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2005 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Label;
-import org.mockito.asm.MethodAdapter;
-import org.mockito.asm.MethodVisitor;
-import org.mockito.asm.Opcodes;
-import org.mockito.asm.Type;
-
-/**
- * A {@link MethodAdapter} that renumbers local variables in their order of
- * appearance. This adapter allows one to easily add new local variables to a
- * method.
- * 
- * @author Chris Nokleberg
- * @author Eric Bruneton
- */
-public class LocalVariablesSorter extends MethodAdapter {
-
-    /**
-     * Mapping from old to new local variable indexes. A local variable at index
-     * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
-     * index i of size 2 is remapped to 'mapping[2*i+1]'.
-     */
-    private static class State
-    {
-        int[] mapping = new int[40];        
-        int nextLocal;
-    }
-
-    protected final int firstLocal;
-    private final State state;
-
-    public LocalVariablesSorter(
-        final int access,
-        final String desc,
-        final MethodVisitor mv)
-    {
-        super(mv);
-        state = new State();
-        Type[] args = Type.getArgumentTypes(desc);
-        state.nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
-        for (int i = 0; i < args.length; i++) {
-            state.nextLocal += args[i].getSize();
-        }
-        firstLocal = state.nextLocal;
-    }
-
-    public LocalVariablesSorter(LocalVariablesSorter lvs) {
-        super(lvs.mv);
-        state = lvs.state;
-        firstLocal = lvs.firstLocal;
-    }
-
-    public void visitVarInsn(final int opcode, final int var) {
-        int size;
-        switch (opcode) {
-            case Opcodes.LLOAD:
-            case Opcodes.LSTORE:
-            case Opcodes.DLOAD:
-            case Opcodes.DSTORE:
-                size = 2;
-                break;
-            default:
-                size = 1;
-        }
-        mv.visitVarInsn(opcode, remap(var, size));
-    }
-
-    public void visitIincInsn(final int var, final int increment) {
-        mv.visitIincInsn(remap(var, 1), increment);
-    }
-
-    public void visitMaxs(final int maxStack, final int maxLocals) {
-        mv.visitMaxs(maxStack, state.nextLocal);
-    }
-
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
-        mv.visitLocalVariable(name, desc, signature, start, end, remap(index));
-    }
-
-    // -------------
-
-    protected int newLocal(final int size) {
-        int var = state.nextLocal;
-        state.nextLocal += size;
-        return var;
-    }
-
-    private int remap(final int var, final int size) {
-        if (var < firstLocal) {
-            return var;
-        }
-        int key = 2 * var + size - 1;
-        int length = state.mapping.length;
-        if (key >= length) {
-            int[] newMapping = new int[Math.max(2 * length, key + 1)];
-            System.arraycopy(state.mapping, 0, newMapping, 0, length);
-            state.mapping = newMapping;
-        }
-        int value = state.mapping[key];
-        if (value == 0) {
-            value = state.nextLocal + 1;
-            state.mapping[key] = value;
-            state.nextLocal += size;
-        }
-        return value - 1;
-    }
-
-    private int remap(final int var) {
-        if (var < firstLocal) {
-            return var;
-        }
-        int key = 2 * var;
-        int value = key < state.mapping.length ? state.mapping[key] : 0;
-        if (value == 0) {
-            value = key + 1 < state.mapping.length ? state.mapping[key + 1] : 0;
-        }
-        if (value == 0) {
-            throw new IllegalStateException("Unknown local variable " + var);
-        }
-        return value - 1;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/MethodInfo.java b/cglib-and-asm/src/org/mockito/cglib/core/MethodInfo.java
deleted file mode 100644
index 4fb32b4..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/MethodInfo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.Type;
-
-abstract public class MethodInfo {
-
-    protected MethodInfo() {
-    }
-    
-    abstract public ClassInfo getClassInfo();
-    abstract public int getModifiers();
-    abstract public Signature getSignature();
-    abstract public Type[] getExceptionTypes();
-
-    public boolean equals(Object o) {
-        if (o == null)
-            return false;
-        if (!(o instanceof MethodInfo))
-            return false;
-        return getSignature().equals(((MethodInfo)o).getSignature());
-    }
-
-    public int hashCode() {
-        return getSignature().hashCode();
-    }
-
-    public String toString() {
-        // TODO: include modifiers, exceptions
-        return getSignature().toString();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/MethodInfoTransformer.java b/cglib-and-asm/src/org/mockito/cglib/core/MethodInfoTransformer.java
deleted file mode 100644
index 62bc696..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/MethodInfoTransformer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.lang.reflect.*;
-
-public class MethodInfoTransformer implements Transformer
-{
-    private static final MethodInfoTransformer INSTANCE = new MethodInfoTransformer();
-
-    public static MethodInfoTransformer getInstance() {
-        return INSTANCE;
-    }
-    
-    public Object transform(Object value) {
-        if (value instanceof Method) {
-            return ReflectUtils.getMethodInfo((Method)value);
-        } else if (value instanceof Constructor) {
-            return ReflectUtils.getMethodInfo((Constructor)value);
-        } else {
-            throw new IllegalArgumentException("cannot get method info for " + value);
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/MethodWrapper.java b/cglib-and-asm/src/org/mockito/cglib/core/MethodWrapper.java
deleted file mode 100644
index 34a6984..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/MethodWrapper.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.lang.reflect.Method;
-import java.util.*;
-
-public class MethodWrapper {
-    private static final MethodWrapperKey KEY_FACTORY =
-      (MethodWrapperKey)KeyFactory.create(MethodWrapperKey.class);
-
-    /** Internal interface, only public due to ClassLoader issues. */
-    public interface MethodWrapperKey {
-        public Object newInstance(String name, String[] parameterTypes, String returnType);
-    }
-    
-    private MethodWrapper() {
-    }
-
-    public static Object create(Method method) {
-        return KEY_FACTORY.newInstance(method.getName(),
-                                       ReflectUtils.getNames(method.getParameterTypes()),
-                                       method.getReturnType().getName());
-    }
-
-    public static Set createSet(Collection methods) {
-        Set set = new HashSet();
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            set.add(create((Method)it.next()));
-        }
-        return set;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/NamingPolicy.java b/cglib-and-asm/src/org/mockito/cglib/core/NamingPolicy.java
deleted file mode 100644
index cf0b408..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/NamingPolicy.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.util.Set;
-
-/**
- * Customize the generated class name for {@link AbstractClassGenerator}-based utilities.
- */
-public interface NamingPolicy {
-    /**
-     * Choose a name for a generated class.
-     * @param prefix a dotted-name chosen by the generating class (possibly to put the generated class in a particular package)
-     * @param source the fully-qualified class name of the generating class (for example "org.mockito.cglib.Enhancer")
-     * @param key A key object representing the state of the parameters; for caching to work properly, equal keys should result
-     * in the same generated class name. The default policy incorporates <code>key.hashCode()</code> into the class name.
-     * @param names a predicate that returns true if the given classname has already been used in the same ClassLoader.
-     * @return the fully-qualified class name
-     */
-    String getClassName(String prefix, String source, Object key, Predicate names);
-
-    /**
-     * The <code>NamingPolicy</code> in use does not currently, but may
-     * in the future, affect the caching of classes generated by {@link
-     * AbstractClassGenerator}, so this is a reminder that you should
-     * correctly implement <code>equals</code> and <code>hashCode</code>
-     * to avoid generating too many classes.
-     */
-    boolean equals(Object o);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ObjectSwitchCallback.java b/cglib-and-asm/src/org/mockito/cglib/core/ObjectSwitchCallback.java
deleted file mode 100644
index ed52fd8..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ObjectSwitchCallback.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Label;
-
-public interface ObjectSwitchCallback {
-    void processCase(Object key, Label end) throws Exception;
-    void processDefault() throws Exception;
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Predicate.java b/cglib-and-asm/src/org/mockito/cglib/core/Predicate.java
deleted file mode 100644
index b014dc8..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Predicate.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-public interface Predicate {
-    boolean evaluate(Object arg);
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ProcessArrayCallback.java b/cglib-and-asm/src/org/mockito/cglib/core/ProcessArrayCallback.java
deleted file mode 100644
index fd85bce..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ProcessArrayCallback.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Type;
-
-public interface ProcessArrayCallback {
-    void processElement(Type type);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ProcessSwitchCallback.java b/cglib-and-asm/src/org/mockito/cglib/core/ProcessSwitchCallback.java
deleted file mode 100644
index 8fbe4d5..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ProcessSwitchCallback.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Label;
-
-public interface ProcessSwitchCallback {
-    void processCase(int key, Label end) throws Exception;
-    void processDefault() throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/ReflectUtils.java b/cglib-and-asm/src/org/mockito/cglib/core/ReflectUtils.java
deleted file mode 100644
index bbc388b..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/ReflectUtils.java
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.beans.*;
-import java.lang.reflect.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.*;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.Type;
-
-/**
- * @version $Id: ReflectUtils.java,v 1.29 2006/02/28 00:30:51 herbyderby Exp $
- */
-public class ReflectUtils {
-    private ReflectUtils() { }
-    
-    private static final Map primitives = new HashMap(8);
-    private static final Map transforms = new HashMap(8);
-    private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader();
-    private static Method DEFINE_CLASS;
-    private static final ProtectionDomain PROTECTION_DOMAIN;
-    
-    static {
-        PROTECTION_DOMAIN = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
-                return ReflectUtils.class.getProtectionDomain();
-            }
-        });
-        
-        AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
-                try {
-                    Class loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this
-                    DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
-                                                            new Class[]{ String.class,
-                                                                         byte[].class,
-                                                                         Integer.TYPE,
-                                                                         Integer.TYPE,
-                                                                         ProtectionDomain.class });
-                    DEFINE_CLASS.setAccessible(true);
-                } catch (ClassNotFoundException e) {
-                    throw new CodeGenerationException(e);
-                } catch (NoSuchMethodException e) {
-                    throw new CodeGenerationException(e);
-                }
-                return null;
-            }
-        });
-    }
-        
-    private static final String[] CGLIB_PACKAGES = {
-        "java.lang",
-    };
-        
-    static {
-        primitives.put("byte", Byte.TYPE);
-        primitives.put("char", Character.TYPE);
-        primitives.put("double", Double.TYPE);
-        primitives.put("float", Float.TYPE);
-        primitives.put("int", Integer.TYPE);
-        primitives.put("long", Long.TYPE);
-        primitives.put("short", Short.TYPE);
-        primitives.put("boolean", Boolean.TYPE);
-            
-        transforms.put("byte", "B");
-        transforms.put("char", "C");
-        transforms.put("double", "D");
-        transforms.put("float", "F");
-        transforms.put("int", "I");
-        transforms.put("long", "J");
-        transforms.put("short", "S");
-        transforms.put("boolean", "Z");
-    }
-        
-    public static Type[] getExceptionTypes(Member member) {
-        if (member instanceof Method) {
-            return TypeUtils.getTypes(((Method)member).getExceptionTypes());
-        } else if (member instanceof Constructor) {
-            return TypeUtils.getTypes(((Constructor)member).getExceptionTypes());
-        } else {
-            throw new IllegalArgumentException("Cannot get exception types of a field");
-        }
-    }
-        
-    public static Signature getSignature(Member member) {
-        if (member instanceof Method) {
-            return new Signature(member.getName(), Type.getMethodDescriptor((Method)member));
-        } else if (member instanceof Constructor) {
-            Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes());
-            return new Signature(Constants.CONSTRUCTOR_NAME,
-                                 Type.getMethodDescriptor(Type.VOID_TYPE, types));
-                
-        } else {
-            throw new IllegalArgumentException("Cannot get signature of a field");
-        }
-    }
-        
-    public static Constructor findConstructor(String desc) {
-        return findConstructor(desc, defaultLoader);
-    }
-        
-    public static Constructor findConstructor(String desc, ClassLoader loader) {
-        try {
-            int lparen = desc.indexOf('(');
-            String className = desc.substring(0, lparen).trim();
-            return getClass(className, loader).getConstructor(parseTypes(desc, loader));
-        } catch (ClassNotFoundException e) {
-            throw new CodeGenerationException(e);
-        } catch (NoSuchMethodException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-        
-    public static Method findMethod(String desc) {
-        return findMethod(desc, defaultLoader);
-    }
-        
-    public static Method findMethod(String desc, ClassLoader loader) {
-        try {
-            int lparen = desc.indexOf('(');
-            int dot = desc.lastIndexOf('.', lparen);
-            String className = desc.substring(0, dot).trim();
-            String methodName = desc.substring(dot + 1, lparen).trim();
-            return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader));
-        } catch (ClassNotFoundException e) {
-            throw new CodeGenerationException(e);
-        } catch (NoSuchMethodException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-        
-    private static Class[] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException {
-        int lparen = desc.indexOf('(');
-        int rparen = desc.indexOf(')', lparen);
-        List params = new ArrayList();
-        int start = lparen + 1;
-        for (;;) {
-            int comma = desc.indexOf(',', start);
-            if (comma < 0) {
-                break;
-            }
-            params.add(desc.substring(start, comma).trim());
-            start = comma + 1;
-        }
-        if (start < rparen) {
-            params.add(desc.substring(start, rparen).trim());
-        }
-        Class[] types = new Class[params.size()];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = getClass((String)params.get(i), loader);
-        }
-        return types;
-    }
-        
-    private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException {
-        return getClass(className, loader, CGLIB_PACKAGES);
-    }
-        
-    private static Class getClass(String className, ClassLoader loader, String[] packages) throws ClassNotFoundException {
-        String save = className;
-        int dimensions = 0;
-        int index = 0;
-        while ((index = className.indexOf("[]", index) + 1) > 0) {
-            dimensions++;
-        }
-        StringBuffer brackets = new StringBuffer(className.length() - dimensions);
-        for (int i = 0; i < dimensions; i++) {
-            brackets.append('[');
-        }
-        className = className.substring(0, className.length() - 2 * dimensions);
-            
-        String prefix = (dimensions > 0) ? brackets + "L" : "";
-        String suffix = (dimensions > 0) ? ";" : "";
-        try {
-            return Class.forName(prefix + className + suffix, false, loader);
-        } catch (ClassNotFoundException ignore) { }
-        for (int i = 0; i < packages.length; i++) {
-            try {
-                return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader);
-            } catch (ClassNotFoundException ignore) { }
-        }
-        if (dimensions == 0) {
-            Class c = (Class)primitives.get(className);
-            if (c != null) {
-                return c;
-            }
-        } else {
-            String transform = (String)transforms.get(className);
-            if (transform != null) {
-                try {
-                    return Class.forName(brackets + transform, false, loader);
-                } catch (ClassNotFoundException ignore) { }
-            }
-        }
-        throw new ClassNotFoundException(save);
-    }
-        
-        
-    public static Object newInstance(Class type) {
-        return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
-    }
-        
-    public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
-        return newInstance(getConstructor(type, parameterTypes), args);
-    }
-        
-    public static Object newInstance(final Constructor cstruct, final Object[] args) {
-            
-        boolean flag = cstruct.isAccessible();
-        try {
-            cstruct.setAccessible(true);
-            Object result = cstruct.newInstance(args);
-            return result;
-        } catch (InstantiationException e) {
-            throw new CodeGenerationException(e);
-        } catch (IllegalAccessException e) {
-            throw new CodeGenerationException(e);
-        } catch (InvocationTargetException e) {
-            throw new CodeGenerationException(e.getTargetException());
-        } finally {
-            cstruct.setAccessible(flag);
-        }
-                
-    }
-        
-    public static Constructor getConstructor(Class type, Class[] parameterTypes) {
-        try {
-            Constructor constructor = type.getDeclaredConstructor(parameterTypes);
-            constructor.setAccessible(true);
-            return constructor;
-        } catch (NoSuchMethodException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-
-    public static String[] getNames(Class[] classes)
-    {
-        if (classes == null)
-            return null;
-        String[] names = new String[classes.length];
-        for (int i = 0; i < names.length; i++) {
-            names[i] = classes[i].getName();
-        }
-        return names;
-    }
-        
-    public static Class[] getClasses(Object[] objects) {
-        Class[] classes = new Class[objects.length];
-        for (int i = 0; i < objects.length; i++) {
-            classes[i] = objects[i].getClass();
-        }
-        return classes;
-    }
-        
-    public static Method findNewInstance(Class iface) {
-        Method m = findInterfaceMethod(iface);
-        if (!m.getName().equals("newInstance")) {
-            throw new IllegalArgumentException(iface + " missing newInstance method");
-        }
-        return m;
-    }
-
-    public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) {
-        Set methods = new HashSet();
-        for (int i = 0; i < properties.length; i++) {
-            PropertyDescriptor pd = properties[i];
-            if (read) {
-                methods.add(pd.getReadMethod());
-            }
-            if (write) {
-                methods.add(pd.getWriteMethod());
-            }
-        }
-        methods.remove(null);
-        return (Method[])methods.toArray(new Method[methods.size()]);
-    }
-        
-    public static PropertyDescriptor[] getBeanProperties(Class type) {
-        return getPropertiesHelper(type, true, true);
-    }
-        
-    public static PropertyDescriptor[] getBeanGetters(Class type) {
-        return getPropertiesHelper(type, true, false);
-    }
-        
-    public static PropertyDescriptor[] getBeanSetters(Class type) {
-        return getPropertiesHelper(type, false, true);
-    }
-        
-    private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) {
-        try {
-            BeanInfo info = Introspector.getBeanInfo(type, Object.class);
-            PropertyDescriptor[] all = info.getPropertyDescriptors();
-            if (read && write) {
-                return all;
-            }
-            List properties = new ArrayList(all.length);
-            for (int i = 0; i < all.length; i++) {
-                PropertyDescriptor pd = all[i];
-                if ((read && pd.getReadMethod() != null) ||
-                    (write && pd.getWriteMethod() != null)) {
-                    properties.add(pd);
-                }
-            }
-            return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]);
-        } catch (IntrospectionException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-        
-        
-        
-    public static Method findDeclaredMethod(final Class type,
-                                            final String methodName, final Class[] parameterTypes)
-    throws NoSuchMethodException {
-                        
-        Class cl = type;
-        while (cl != null) {
-            try {
-                return cl.getDeclaredMethod(methodName, parameterTypes);
-            } catch (NoSuchMethodException e) {
-                cl = cl.getSuperclass();
-            }
-        }
-        throw new NoSuchMethodException(methodName);
-            
-    }
-        
-    public static List addAllMethods(final Class type, final List list) {
-            
-            
-        list.addAll(java.util.Arrays.asList(type.getDeclaredMethods()));
-        Class superclass = type.getSuperclass();
-        if (superclass != null) {
-            addAllMethods(superclass, list);
-        }
-        Class[] interfaces = type.getInterfaces();
-        for (int i = 0; i < interfaces.length; i++) {
-            addAllMethods(interfaces[i], list);
-        }
-            
-        return list;
-    }
-        
-    public static List addAllInterfaces(Class type, List list) {
-        Class superclass = type.getSuperclass();
-        if (superclass != null) {
-            list.addAll(Arrays.asList(type.getInterfaces()));
-            addAllInterfaces(superclass, list);
-        }
-        return list;
-    }
-        
-        
-    public static Method findInterfaceMethod(Class iface) {
-        if (!iface.isInterface()) {
-            throw new IllegalArgumentException(iface + " is not an interface");
-        }
-        Method[] methods = iface.getDeclaredMethods();
-        if (methods.length != 1) {
-            throw new IllegalArgumentException("expecting exactly 1 method in " + iface);
-        }
-        return methods[0];
-    }
-        
-    public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
-        Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
-        return (Class)DEFINE_CLASS.invoke(loader, args);
-    }
-        
-    public static int findPackageProtected(Class[] classes) {
-        for (int i = 0; i < classes.length; i++) {
-            if (!Modifier.isPublic(classes[i].getModifiers())) {
-                return i;
-            }
-        }
-        return 0;
-    }
-
-    public static MethodInfo getMethodInfo(final Member member, final int modifiers) {
-        final Signature sig = getSignature(member);
-        return new MethodInfo() {
-            private ClassInfo ci;
-            public ClassInfo getClassInfo() {
-                if (ci == null)
-                    ci = ReflectUtils.getClassInfo(member.getDeclaringClass());
-                return ci;
-            }
-            public int getModifiers() {
-                return modifiers;
-            }
-            public Signature getSignature() {
-                return sig;
-            }
-            public Type[] getExceptionTypes() {
-                return ReflectUtils.getExceptionTypes(member);
-            }
-            public Attribute getAttribute() {
-                return null;
-            }
-        };
-    }
-
-    public static MethodInfo getMethodInfo(Member member) {
-        return getMethodInfo(member, member.getModifiers());
-    }
-
-    public static ClassInfo getClassInfo(final Class clazz) {
-        final Type type = Type.getType(clazz);
-        final Type sc = (clazz.getSuperclass() == null) ? null : Type.getType(clazz.getSuperclass());
-        return new ClassInfo() {
-            public Type getType() {
-                return type;
-            }
-            public Type getSuperType() {
-                return sc;
-            }
-            public Type[] getInterfaces() {
-                return TypeUtils.getTypes(clazz.getInterfaces());
-            }
-            public int getModifiers() {
-                return clazz.getModifiers();
-            }
-        };
-    }
-
-    // used by MethodInterceptorGenerated generated code
-    public static Method[] findMethods(String[] namesAndDescriptors, Method[] methods)
-    {
-        Map map = new HashMap();
-        for (int i = 0; i < methods.length; i++) {
-            Method method = methods[i];
-            map.put(method.getName() + Type.getMethodDescriptor(method), method);
-        }
-        Method[] result = new Method[namesAndDescriptors.length / 2];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]);
-            if (result[i] == null) {
-                // TODO: error?
-            }
-        }
-        return result;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/RejectModifierPredicate.java b/cglib-and-asm/src/org/mockito/cglib/core/RejectModifierPredicate.java
deleted file mode 100644
index b7255ca..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/RejectModifierPredicate.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.lang.reflect.*;
-
-public class RejectModifierPredicate implements Predicate {
-    private int rejectMask;
-
-    public RejectModifierPredicate(int rejectMask) {
-        this.rejectMask = rejectMask;
-    }
-
-    public boolean evaluate(Object arg) {
-        return (((Member)arg).getModifiers() & rejectMask) == 0;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Signature.java b/cglib-and-asm/src/org/mockito/cglib/core/Signature.java
deleted file mode 100644
index ebb47b9..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Signature.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import org.mockito.asm.Type;
-
-/**
- * A representation of a method signature, containing the method name,
- * return type, and parameter types.
- */
-public class Signature {
-    private String name;
-    private String desc;
-
-    public Signature(String name, String desc) {
-        // TODO: better error checking
-        if (name.indexOf('(') >= 0) {
-            throw new IllegalArgumentException("Name '" + name + "' is invalid");
-        }
-        this.name = name;
-        this.desc = desc;
-    }
-
-    public Signature(String name, Type returnType, Type[] argumentTypes) {
-        this(name, Type.getMethodDescriptor(returnType, argumentTypes));
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getDescriptor() {
-        return desc;
-    }
-
-    public Type getReturnType() {
-        return Type.getReturnType(desc);
-    }
-
-    public Type[] getArgumentTypes() {
-        return Type.getArgumentTypes(desc);
-    }
-
-    public String toString() {
-        return name + desc;
-    }
-
-    public boolean equals(Object o) {
-        if (o == null)
-            return false;
-        if (!(o instanceof Signature))
-            return false;
-        Signature other = (Signature)o;
-        return name.equals(other.name) && desc.equals(other.desc);
-    }
-
-    public int hashCode() {
-        return name.hashCode() ^ desc.hashCode();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/TinyBitSet.java b/cglib-and-asm/src/org/mockito/cglib/core/TinyBitSet.java
deleted file mode 100644
index 964bcd0..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/TinyBitSet.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-public class TinyBitSet {
-    private static int[] T = new int[256];
-    private int value = 0;
-
-    private static int gcount(int x) {
-        int c = 0;
-        while (x != 0) {
-            c++;
-            x &= (x - 1);
-        }
-        return c;
-    }
-
-    static {
-        for(int j = 0; j < 256; j++) {
-            T[j] = gcount(j);
-        }
-    }
-
-    private static int topbit(int i) {
-        int j;
-        for (j = 0; i != 0; i ^= j) {
-            j = i & -i;
-        }
-        return j;
-    }
-
-    private static int log2(int i) {
-        int j = 0;
-        for (j = 0; i != 0; i >>= 1) {
-            j++;
-        }
-        return j;
-    }
-    
-    public int length() {
-        return log2(topbit(value));
-    }
-
-    public int cardinality() {
-        int w = value;
-        int c = 0;
-        while (w != 0) {
-            c += T[w & 255];
-            w >>= 8;
-        }
-        return c;
-    }
-
-    public boolean get(int index) {
-        return (value & (1 << index)) != 0;
-    }
-
-    public void set(int index) {
-        value |= (1 << index);
-    }
-
-    public void clear(int index) {
-        value &= ~(1 << index);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/Transformer.java b/cglib-and-asm/src/org/mockito/cglib/core/Transformer.java
deleted file mode 100644
index dfdc030..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/Transformer.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-public interface Transformer {
-    Object transform(Object value);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/TypeUtils.java b/cglib-and-asm/src/org/mockito/cglib/core/TypeUtils.java
deleted file mode 100644
index ded95b8..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/TypeUtils.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.util.*;
-
-import org.mockito.asm.Type;
-
-public class TypeUtils {
-    private static final Map transforms = new HashMap();
-    private static final Map rtransforms = new HashMap();
-
-    private TypeUtils() {
-    }
-
-    static {
-        transforms.put("void", "V");
-        transforms.put("byte", "B");
-        transforms.put("char", "C");
-        transforms.put("double", "D");
-        transforms.put("float", "F");
-        transforms.put("int", "I");
-        transforms.put("long", "J");
-        transforms.put("short", "S");
-        transforms.put("boolean", "Z");
-
-        CollectionUtils.reverse(transforms, rtransforms);
-    }
-
-    public static Type getType(String className) {
-        return Type.getType("L" + className.replace('.', '/') + ";");
-    }
-
-    public static boolean isFinal(int access) {
-        return (Constants.ACC_FINAL & access) != 0;
-    }
-
-    public static boolean isStatic(int access) {
-        return (Constants.ACC_STATIC & access) != 0;
-    }
-
-    public static boolean isProtected(int access) {
-        return (Constants.ACC_PROTECTED & access) != 0;
-    }
-
-    public static boolean isPublic(int access) {
-        return (Constants.ACC_PUBLIC & access) != 0;
-    }
-
-    public static boolean isAbstract(int access) {
-        return (Constants.ACC_ABSTRACT & access) != 0;
-    }
-    
-    public static boolean isInterface(int access) {
-        return (Constants.ACC_INTERFACE & access) != 0;
-    }
-
-    public static boolean isPrivate(int access) {
-        return (Constants.ACC_PRIVATE & access) != 0;
-    }
-    
-    public static boolean isSynthetic(int access) {
-        return (Constants.ACC_SYNTHETIC & access) != 0;
-    }
-    
-    // getPackage returns null on JDK 1.2
-    public static String getPackageName(Type type) {
-        return getPackageName(getClassName(type));
-    }
-
-    public static String getPackageName(String className) {
-        int idx = className.lastIndexOf('.');
-        return (idx < 0) ? "" : className.substring(0, idx);
-    }
-    
-    public static String upperFirst(String s) {
-        if (s == null || s.length() == 0) {
-            return s;
-        }
-        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
-    }
-
-    public static String getClassName(Type type) {
-        if (isPrimitive(type)) {
-            return (String)rtransforms.get(type.getDescriptor());
-        } else if (isArray(type)) {
-            return getClassName(getComponentType(type)) + "[]";
-        } else {
-            return type.getClassName();
-        }
-    }
-
-    public static Type[] add(Type[] types, Type extra) {
-        if (types == null) {
-            return new Type[]{ extra };
-        } else {
-            List list = Arrays.asList(types);
-            if (list.contains(extra)) {
-                return types;
-            }
-            Type[] copy = new Type[types.length + 1];
-            System.arraycopy(types, 0, copy, 0, types.length);
-            copy[types.length] = extra;
-            return copy;
-        }
-    }
-
-    public static Type[] add(Type[] t1, Type[] t2) {
-        // TODO: set semantics?
-        Type[] all = new Type[t1.length + t2.length];
-        System.arraycopy(t1, 0, all, 0, t1.length);
-        System.arraycopy(t2, 0, all, t1.length, t2.length);
-        return all;
-    }
-
-    public static Type fromInternalName(String name) {
-        // TODO; primitives?
-        return Type.getType("L" + name + ";");
-    }
-
-    public static Type[] fromInternalNames(String[] names) {
-        if (names == null) {
-            return null;
-        }
-        Type[] types = new Type[names.length];
-        for (int i = 0; i < names.length; i++) {
-            types[i] = fromInternalName(names[i]);
-        }
-        return types;
-    }
-
-    public static int getStackSize(Type[] types) {
-        int size = 0;
-        for (int i = 0; i < types.length; i++) {
-            size += types[i].getSize();
-        }
-        return size;
-    }
-
-    public static String[] toInternalNames(Type[] types) {
-        if (types == null) {
-            return null;
-        }
-        String[] names = new String[types.length];
-        for (int i = 0; i < types.length; i++) {
-            names[i] = types[i].getInternalName();
-        }
-        return names;
-    }
-
-    public static Signature parseSignature(String s) {
-        int space = s.indexOf(' ');
-        int lparen = s.indexOf('(', space);
-        int rparen = s.indexOf(')', lparen);
-        String returnType = s.substring(0, space);
-        String methodName = s.substring(space + 1, lparen);
-        StringBuffer sb = new StringBuffer();
-        sb.append('(');
-        for (Iterator it = parseTypes(s, lparen + 1, rparen).iterator(); it.hasNext();) {
-            sb.append(it.next());
-        }
-        sb.append(')');
-        sb.append(map(returnType));
-        return new Signature(methodName, sb.toString());
-    }
-
-    public static Type parseType(String s) {
-        return Type.getType(map(s));
-    }
-
-    public static Type[] parseTypes(String s) {
-        List names = parseTypes(s, 0, s.length());
-        Type[] types = new Type[names.size()];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = Type.getType((String)names.get(i));
-        }
-        return types;
-    }
-
-    public static Signature parseConstructor(Type[] types) {
-        StringBuffer sb = new StringBuffer();
-        sb.append("(");
-        for (int i = 0; i < types.length; i++) {
-            sb.append(types[i].getDescriptor());
-        }
-        sb.append(")");
-        sb.append("V");
-        return new Signature(Constants.CONSTRUCTOR_NAME, sb.toString());
-    }
-
-    public static Signature parseConstructor(String sig) {
-        return parseSignature("void <init>(" + sig + ")"); // TODO
-    }
-
-    private static List parseTypes(String s, int mark, int end) {
-        List types = new ArrayList(5);
-        for (;;) {
-            int next = s.indexOf(',', mark);
-            if (next < 0) {
-                break;
-            }
-            types.add(map(s.substring(mark, next).trim()));
-            mark = next + 1;
-        }
-        types.add(map(s.substring(mark, end).trim()));
-        return types;
-    }
-
-    private static String map(String type) {
-        if (type.equals("")) {
-            return type;
-        }
-        String t = (String)transforms.get(type);
-        if (t != null) {
-            return t;
-        } else if (type.indexOf('.') < 0) {
-            return map("java.lang." + type);
-        } else {
-            StringBuffer sb = new StringBuffer();
-            int index = 0;
-            while ((index = type.indexOf("[]", index) + 1) > 0) {
-                sb.append('[');
-            }
-            type = type.substring(0, type.length() - sb.length() * 2);
-            sb.append('L').append(type.replace('.', '/')).append(';');
-            return sb.toString();
-        }
-    }
-
-    public static Type getBoxedType(Type type) {
-        switch (type.getSort()) {
-        case Type.CHAR:
-            return Constants.TYPE_CHARACTER;
-        case Type.BOOLEAN:
-            return Constants.TYPE_BOOLEAN;
-        case Type.DOUBLE:
-            return Constants.TYPE_DOUBLE;
-        case Type.FLOAT:
-            return Constants.TYPE_FLOAT;
-        case Type.LONG:
-            return Constants.TYPE_LONG;
-        case Type.INT:
-            return Constants.TYPE_INTEGER;
-        case Type.SHORT:
-            return Constants.TYPE_SHORT;
-        case Type.BYTE:
-            return Constants.TYPE_BYTE;
-        default:
-            return type;
-        }
-    }
-
-    public static Type getUnboxedType(Type type) {
-        if (Constants.TYPE_INTEGER.equals(type)) {
-            return Type.INT_TYPE;
-        } else if (Constants.TYPE_BOOLEAN.equals(type)) {
-            return Type.BOOLEAN_TYPE;
-        } else if (Constants.TYPE_DOUBLE.equals(type)) {
-            return Type.DOUBLE_TYPE;
-        } else if (Constants.TYPE_LONG.equals(type)) {
-            return Type.LONG_TYPE;
-        } else if (Constants.TYPE_CHARACTER.equals(type)) {
-            return Type.CHAR_TYPE;
-        } else if (Constants.TYPE_BYTE.equals(type)) {
-            return Type.BYTE_TYPE;
-        } else if (Constants.TYPE_FLOAT.equals(type)) {
-            return Type.FLOAT_TYPE;
-        } else if (Constants.TYPE_SHORT.equals(type)) {
-            return Type.SHORT_TYPE;
-        } else {
-            return type;
-        }
-    }
-
-    public static boolean isArray(Type type) {
-        return type.getSort() == Type.ARRAY;
-    }
-
-    public static Type getComponentType(Type type) {
-        if (!isArray(type)) {
-            throw new IllegalArgumentException("Type " + type + " is not an array");
-        }
-        return Type.getType(type.getDescriptor().substring(1));
-    }
-
-    public static boolean isPrimitive(Type type) {
-        switch (type.getSort()) {
-        case Type.ARRAY:
-        case Type.OBJECT:
-            return false;
-        default:
-            return true;
-        }
-    }
-
-    public static String emulateClassGetName(Type type) {
-        if (isArray(type)) {
-            return type.getDescriptor().replace('/', '.');
-        } else {
-            return getClassName(type);
-        }
-    }
-
-    public static boolean isConstructor(MethodInfo method) {
-        return method.getSignature().getName().equals(Constants.CONSTRUCTOR_NAME);
-    }
-
-    public static Type[] getTypes(Class[] classes) {
-        if (classes == null) {
-            return null;
-        }
-        Type[] types = new Type[classes.length];
-        for (int i = 0; i < classes.length; i++) {
-            types[i] = Type.getType(classes[i]);
-        }
-        return types;
-    }
-
-    public static int ICONST(int value) {
-        switch (value) {
-        case -1: return Constants.ICONST_M1;
-        case 0: return Constants.ICONST_0;
-        case 1: return Constants.ICONST_1;
-        case 2: return Constants.ICONST_2;
-        case 3: return Constants.ICONST_3;
-        case 4: return Constants.ICONST_4;
-        case 5: return Constants.ICONST_5;
-        }
-        return -1; // error
-    }
-
-    public static int LCONST(long value) {
-        if (value == 0L) {
-            return Constants.LCONST_0;
-        } else if (value == 1L) {
-            return Constants.LCONST_1;
-        } else {
-            return -1; // error
-        }
-    }
-
-    public static int FCONST(float value) {
-        if (value == 0f) {
-            return Constants.FCONST_0;
-        } else if (value == 1f) {
-            return Constants.FCONST_1;
-        } else if (value == 2f) {
-            return Constants.FCONST_2;
-        } else {
-            return -1; // error
-        }
-    }
-
-    public static int DCONST(double value) {
-        if (value == 0d) {
-            return Constants.DCONST_0;
-        } else if (value == 1d) {
-            return Constants.DCONST_1;
-        } else {
-            return -1; // error
-        }
-    }
-
-    public static int NEWARRAY(Type type) {
-        switch (type.getSort()) {
-        case Type.BYTE:
-            return Constants.T_BYTE;
-        case Type.CHAR:
-            return Constants.T_CHAR;
-        case Type.DOUBLE:
-            return Constants.T_DOUBLE;
-        case Type.FLOAT:
-            return Constants.T_FLOAT;
-        case Type.INT:
-            return Constants.T_INT;
-        case Type.LONG:
-            return Constants.T_LONG;
-        case Type.SHORT:
-            return Constants.T_SHORT;
-        case Type.BOOLEAN:
-            return Constants.T_BOOLEAN;
-        default:
-            return -1; // error
-        }
-    }
-
-    public static String escapeType(String s) {
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0, len = s.length(); i < len; i++) {
-            char c = s.charAt(i);
-            switch (c) {
-            case '$': sb.append("$24"); break;
-            case '.': sb.append("$2E"); break;
-            case '[': sb.append("$5B"); break;
-            case ';': sb.append("$3B"); break;
-            case '(': sb.append("$28"); break;
-            case ')': sb.append("$29"); break;
-            case '/': sb.append("$2F"); break;
-            default:
-                sb.append(c);
-            }
-        }
-        return sb.toString();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/core/VisibilityPredicate.java b/cglib-and-asm/src/org/mockito/cglib/core/VisibilityPredicate.java
deleted file mode 100644
index 335cf72..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/core/VisibilityPredicate.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.core;
-
-import java.lang.reflect.*;
-
-import org.mockito.asm.Type;
-
-public class VisibilityPredicate implements Predicate {
-    private boolean protectedOk;
-    private String pkg;
-
-    public VisibilityPredicate(Class source, boolean protectedOk) {
-        this.protectedOk = protectedOk;
-        pkg = TypeUtils.getPackageName(Type.getType(source));
-    }
-
-    public boolean evaluate(Object arg) {
-        int mod = (arg instanceof Member) ? ((Member)arg).getModifiers() : ((Integer)arg).intValue();
-        if (Modifier.isPrivate(mod)) {
-            return false;
-        } else if (Modifier.isPublic(mod)) {
-            return true;
-        } else if (Modifier.isProtected(mod)) {
-            return protectedOk;
-        } else {
-            return pkg.equals(TypeUtils.getPackageName(Type.getType(((Member)arg).getDeclaringClass())));
-        }
-    }
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/Callback.java b/cglib-and-asm/src/org/mockito/cglib/proxy/Callback.java
deleted file mode 100644
index e0dcc5e..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/Callback.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * All callback interfaces used by {@link Enhancer} extend this interface.
- * @see MethodInterceptor
- * @see NoOp
- * @see LazyLoader
- * @see Dispatcher
- * @see InvocationHandler
- * @see FixedValue
- */
-public interface Callback
-{
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackFilter.java b/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackFilter.java
deleted file mode 100644
index b81e9b7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackFilter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * Map methods of subclasses generated by {@link Enhancer} to a particular
- * callback. The type of the callbacks chosen for each method affects
- * the bytecode generated for that method in the subclass, and cannot
- * change for the life of the class.
- */
-public interface CallbackFilter {
-    /**
-     * Map a method to a callback.
-     *
-     * @param method the intercepted method
-     * @param allMethods all the methods found on the instance. Don't mess with the contents of this list!!!
-     * @return the index into the array of callbacks (as specified by {@link Enhancer#setCallbacks}) to use for the method,
-     */
-    int accept(Method method, List<Method> allMethods);
-
-    /**
-     * The <code>CallbackFilter</code> in use affects which cached class
-     * the <code>Enhancer</code> will use, so this is a reminder that
-     * you should correctly implement <code>equals</code> and
-     * <code>hashCode</code> for custom <code>CallbackFilter</code>
-     * implementations in order to improve performance.
-    */
-    boolean equals(Object o);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackGenerator.java
deleted file mode 100644
index a0d4ae9..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackGenerator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.util.List;
-
-import org.mockito.cglib.core.*;
-
-interface CallbackGenerator
-{
-    void generate(ClassEmitter ce, Context context, List methods) throws Exception;
-    void generateStatic(CodeEmitter e, Context context, List methods) throws Exception;
-
-    interface Context
-    {
-        ClassLoader getClassLoader();
-        CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method);
-        int getOriginalModifiers(MethodInfo method);
-        int getIndex(MethodInfo method);
-        void emitCallback(CodeEmitter ce, int index);
-        Signature getImplSignature(MethodInfo method);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackHelper.java b/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackHelper.java
deleted file mode 100644
index de5a4e8..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackHelper.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-import java.util.*;
-
-import org.mockito.cglib.core.ReflectUtils;
-
-/**
- * @version $Id: CallbackHelper.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $
- */
-abstract public class CallbackHelper
-implements CallbackFilter
-{
-    private Map methodMap = new HashMap();
-    private List callbacks = new ArrayList();
-    
-    public CallbackHelper(Class superclass, Class[] interfaces)
-    {
-        List methods = new ArrayList();
-        Enhancer.getMethods(superclass, interfaces, methods);
-        Map indexes = new HashMap();
-        for (int i = 0, size = methods.size(); i < size; i++) {
-            Method method = (Method)methods.get(i);
-            Object callback = getCallback(method);
-            if (callback == null)
-                throw new IllegalStateException("getCallback cannot return null");
-            boolean isCallback = callback instanceof Callback;
-            if (!(isCallback || (callback instanceof Class)))
-                throw new IllegalStateException("getCallback must return a Callback or a Class");
-            if (i > 0 && ((callbacks.get(i - 1) instanceof Callback) ^ isCallback))
-                throw new IllegalStateException("getCallback must return a Callback or a Class consistently for every Method");
-            Integer index = (Integer)indexes.get(callback);
-            if (index == null) {
-                index = new Integer(callbacks.size());
-                indexes.put(callback, index);
-            }
-            methodMap.put(method, index);
-            callbacks.add(callback);
-        }
-    }
-
-    abstract protected Object getCallback(Method method);
-
-    public Callback[] getCallbacks()
-    {
-        if (callbacks.size() == 0)
-            return new Callback[0];
-        if (callbacks.get(0) instanceof Callback) {
-            return (Callback[])callbacks.toArray(new Callback[callbacks.size()]);
-        } else {
-            throw new IllegalStateException("getCallback returned classes, not callbacks; call getCallbackTypes instead");
-        }
-    }
-
-    public Class[] getCallbackTypes()
-    {
-        if (callbacks.size() == 0)
-            return new Class[0];
-        if (callbacks.get(0) instanceof Callback) {
-            return ReflectUtils.getClasses(getCallbacks());
-        } else {
-            return (Class[])callbacks.toArray(new Class[callbacks.size()]);
-        }
-    }
-
-    public int accept(Method method, List<Method> allMethods)
-    {
-        return ((Integer)methodMap.get(method)).intValue();
-    }
-
-    public int hashCode()
-    {
-        return methodMap.hashCode();
-    }
-    
-    public boolean equals(Object o)
-    {
-        if (o == null)
-            return false;
-        if (!(o instanceof CallbackHelper))
-            return false;
-        return methodMap.equals(((CallbackHelper)o).methodMap);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackInfo.java b/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackInfo.java
deleted file mode 100644
index 0f14be9..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/CallbackInfo.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import org.mockito.asm.Type;
-
-class CallbackInfo
-{
-    public static Type[] determineTypes(Class[] callbackTypes) {
-        Type[] types = new Type[callbackTypes.length];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = determineType(callbackTypes[i]);
-        }
-        return types;
-    }
-
-    public static Type[] determineTypes(Callback[] callbacks) {
-        Type[] types = new Type[callbacks.length];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = determineType(callbacks[i]);
-        }
-        return types;
-    }
-
-    public static CallbackGenerator[] getGenerators(Type[] callbackTypes) {
-        CallbackGenerator[] generators = new CallbackGenerator[callbackTypes.length];
-        for (int i = 0; i < generators.length; i++) {
-            generators[i] = getGenerator(callbackTypes[i]);
-        }
-        return generators;
-    }
-
-    //////////////////// PRIVATE ////////////////////
-
-    private Class cls;
-    private CallbackGenerator generator;
-    private Type type;
-    
-    private static final CallbackInfo[] CALLBACKS = {
-        new CallbackInfo(NoOp.class, NoOpGenerator.INSTANCE),
-        new CallbackInfo(MethodInterceptor.class, MethodInterceptorGenerator.INSTANCE),
-        new CallbackInfo(InvocationHandler.class, InvocationHandlerGenerator.INSTANCE),
-        new CallbackInfo(LazyLoader.class, LazyLoaderGenerator.INSTANCE),
-        new CallbackInfo(Dispatcher.class, DispatcherGenerator.INSTANCE),
-        new CallbackInfo(FixedValue.class, FixedValueGenerator.INSTANCE),
-        new CallbackInfo(ProxyRefDispatcher.class, DispatcherGenerator.PROXY_REF_INSTANCE),
-    };
-
-    private CallbackInfo(Class cls, CallbackGenerator generator) {
-        this.cls = cls;
-        this.generator = generator;
-        type = Type.getType(cls);
-    }
-
-    private static Type determineType(Callback callback) {
-        if (callback == null) {
-            throw new IllegalStateException("Callback is null");
-        }
-        return determineType(callback.getClass());
-    }
-
-    private static Type determineType(Class callbackType) {
-        Class cur = null;
-        for (int i = 0; i < CALLBACKS.length; i++) {
-            CallbackInfo info = CALLBACKS[i];
-            if (info.cls.isAssignableFrom(callbackType)) {
-                if (cur != null) {
-                    throw new IllegalStateException("Callback implements both " + cur + " and " + info.cls);
-                }
-                cur = info.cls;
-            }
-        }
-        if (cur == null) {
-            throw new IllegalStateException("Unknown callback type " + callbackType);
-        }
-        return Type.getType(cur);
-    }
-
-    private static CallbackGenerator getGenerator(Type callbackType) {
-        for (int i = 0; i < CALLBACKS.length; i++) {
-            CallbackInfo info = CALLBACKS[i];
-            if (info.type.equals(callbackType)) {
-                return info.generator;
-            }
-        }
-        throw new IllegalStateException("Unknown callback type " + callbackType);
-    }
-}
-    
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/Dispatcher.java b/cglib-and-asm/src/org/mockito/cglib/proxy/Dispatcher.java
deleted file mode 100644
index b301ea4..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/Dispatcher.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * Dispatching {@link Enhancer} callback. This is identical to the
- * {@link LazyLoader} interface but needs to be separate so that <code>Enhancer</code>
- * knows which type of code to generate.
- */
-public interface Dispatcher extends Callback {
-    /**
-     * Return the object which the original method invocation should
-     * be dispatched. This method is called for <b>every</b> method invocation.
-     * @return an object that can invoke the method
-     */
-    Object loadObject() throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/DispatcherGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/DispatcherGenerator.java
deleted file mode 100644
index ce9e34a..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/DispatcherGenerator.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.util.*;
-
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class DispatcherGenerator implements CallbackGenerator {
-    public static final DispatcherGenerator INSTANCE =
-      new DispatcherGenerator(false);
-    public static final DispatcherGenerator PROXY_REF_INSTANCE =
-      new DispatcherGenerator(true);
-
-    private static final Type DISPATCHER =
-      TypeUtils.parseType("org.mockito.cglib.proxy.Dispatcher");
-    private static final Type PROXY_REF_DISPATCHER =
-      TypeUtils.parseType("org.mockito.cglib.proxy.ProxyRefDispatcher");
-    private static final Signature LOAD_OBJECT =
-      TypeUtils.parseSignature("Object loadObject()");
-    private static final Signature PROXY_REF_LOAD_OBJECT =
-      TypeUtils.parseSignature("Object loadObject(Object)");
-
-    private boolean proxyRef;
-
-    private DispatcherGenerator(boolean proxyRef) {
-        this.proxyRef = proxyRef;
-    }
-
-    public void generate(ClassEmitter ce, Context context, List methods) {
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            if (!TypeUtils.isProtected(method.getModifiers())) {
-                CodeEmitter e = context.beginMethod(ce, method);
-                context.emitCallback(e, context.getIndex(method));
-                if (proxyRef) {
-                    e.load_this();
-                    e.invoke_interface(PROXY_REF_DISPATCHER, PROXY_REF_LOAD_OBJECT);
-                } else {
-                    e.invoke_interface(DISPATCHER, LOAD_OBJECT);
-                }
-                e.checkcast(method.getClassInfo().getType());
-                e.load_args();
-                e.invoke(method);
-                e.return_value();
-                e.end_method();
-            }
-        }
-    }
-
-    public void generateStatic(CodeEmitter e, Context context, List methods) { }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/Enhancer.java b/cglib-and-asm/src/org/mockito/cglib/proxy/Enhancer.java
deleted file mode 100644
index 642db55..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/Enhancer.java
+++ /dev/null
@@ -1,1046 +0,0 @@
-/*
- * Copyright 2002,2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * Generates dynamic subclasses to enable method interception. This
- * class started as a substitute for the standard Dynamic Proxy support
- * included with JDK 1.3, but one that allowed the proxies to extend a
- * concrete base class, in addition to implementing interfaces. The dynamically
- * generated subclasses override the non-final methods of the superclass and
- * have hooks which callback to user-defined interceptor
- * implementations.
- * <p>
- * The original and most general callback type is the {@link MethodInterceptor}, which
- * in AOP terms enables "around advice"--that is, you can invoke custom code both before
- * and after the invocation of the "super" method. In addition you can modify the
- * arguments before calling the super method, or not call it at all.
- * <p>
- * Although <code>MethodInterceptor</code> is generic enough to meet any
- * interception need, it is often overkill. For simplicity and performance, additional
- * specialized callback types, such as {@link LazyLoader} are also available.
- * Often a single callback will be used per enhanced class, but you can control
- * which callback is used on a per-method basis with a {@link CallbackFilter}.
- * <p>
- * The most common uses of this class are embodied in the static helper methods. For
- * advanced needs, such as customizing the <code>ClassLoader</code> to use, you should create
- * a new instance of <code>Enhancer</code>. Other classes within CGLIB follow a similar pattern.
- * <p>
- * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is
- * used to explicitly disable this feature. The <code>Factory</code> interface provides an API
- * to change the callbacks of an existing object, as well as a faster and easier way to create
- * new instances of the same type.
- * <p>
- * For an almost drop-in replacement for
- * <code>java.lang.reflect.Proxy</code>, see the {@link Proxy} class.
- */
-public class Enhancer extends AbstractClassGenerator
-{
-    private static final CallbackFilter ALL_ZERO = new CallbackFilter(){
-        public int accept(Method method, List<Method> allMethods) {
-            return 0;
-        }
-    };
-
-    private static final Source SOURCE = new Source(Enhancer.class.getName());
-    private static final EnhancerKey KEY_FACTORY =
-      (EnhancerKey)KeyFactory.create(EnhancerKey.class);
-
-    private static final String BOUND_FIELD = "CGLIB$BOUND";
-    private static final String THREAD_CALLBACKS_FIELD = "CGLIB$THREAD_CALLBACKS";
-    private static final String STATIC_CALLBACKS_FIELD = "CGLIB$STATIC_CALLBACKS";
-    private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS";
-    private static final String SET_STATIC_CALLBACKS_NAME = "CGLIB$SET_STATIC_CALLBACKS";
-    private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED";
-
-    private static final Type FACTORY =
-      TypeUtils.parseType("org.mockito.cglib.proxy.Factory");
-    private static final Type ILLEGAL_STATE_EXCEPTION =
-      TypeUtils.parseType("IllegalStateException");
-    private static final Type ILLEGAL_ARGUMENT_EXCEPTION =
-      TypeUtils.parseType("IllegalArgumentException");
-    private static final Type THREAD_LOCAL =
-      TypeUtils.parseType("ThreadLocal");
-    private static final Type CALLBACK =
-      TypeUtils.parseType("org.mockito.cglib.proxy.Callback");
-    private static final Type CALLBACK_ARRAY =
-      Type.getType(Callback[].class);
-    private static final Signature CSTRUCT_NULL =
-      TypeUtils.parseConstructor("");
-    private static final Signature SET_THREAD_CALLBACKS =
-      new Signature(SET_THREAD_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY });
-    private static final Signature SET_STATIC_CALLBACKS =
-      new Signature(SET_STATIC_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY });
-    private static final Signature NEW_INSTANCE =
-      new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK_ARRAY });
-    private static final Signature MULTIARG_NEW_INSTANCE =
-      new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{
-          Constants.TYPE_CLASS_ARRAY,
-          Constants.TYPE_OBJECT_ARRAY,
-          CALLBACK_ARRAY,
-      });
-    private static final Signature SINGLE_NEW_INSTANCE =
-      new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK });
-    private static final Signature SET_CALLBACK =
-      new Signature("setCallback", Type.VOID_TYPE, new Type[]{ Type.INT_TYPE, CALLBACK });
-    private static final Signature GET_CALLBACK =
-      new Signature("getCallback", CALLBACK, new Type[]{ Type.INT_TYPE });
-    private static final Signature SET_CALLBACKS =
-      new Signature("setCallbacks", Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY });
-    private static final Signature GET_CALLBACKS =
-      new Signature("getCallbacks", CALLBACK_ARRAY, new Type[0]);
-    private static final Signature THREAD_LOCAL_GET =
-      TypeUtils.parseSignature("Object get()");
-    private static final Signature THREAD_LOCAL_SET =
-      TypeUtils.parseSignature("void set(Object)");
-    private static final Signature BIND_CALLBACKS =
-      TypeUtils.parseSignature("void CGLIB$BIND_CALLBACKS(Object)");
-
-    /** Internal interface, only public due to ClassLoader issues. */
-    public interface EnhancerKey {
-        public Object newInstance(String type,
-                                  String[] interfaces,
-                                  CallbackFilter filter,
-                                  Type[] callbackTypes,
-                                  boolean useFactory,
-                                  boolean interceptDuringConstruction,
-                                  Long serialVersionUID);
-    }
-
-    private Class[] interfaces;
-    private CallbackFilter filter;
-    private Callback[] callbacks;
-    private Type[] callbackTypes;
-    private boolean classOnly;
-    private Class superclass;
-    private Class[] argumentTypes;
-    private Object[] arguments;
-    private boolean useFactory = true;
-    private Long serialVersionUID;
-    private boolean interceptDuringConstruction = true;
-
-    /**
-     * Create a new <code>Enhancer</code>. A new <code>Enhancer</code>
-     * object should be used for each generated object, and should not
-     * be shared across threads. To create additional instances of a
-     * generated class, use the <code>Factory</code> interface.
-     * @see Factory
-     */
-    public Enhancer() {
-        super(SOURCE);
-    }
-
-    /**
-     * Set the class which the generated class will extend. As a convenience,
-     * if the supplied superclass is actually an interface, <code>setInterfaces</code>
-     * will be called with the appropriate argument instead.
-     * A non-interface argument must not be declared as final, and must have an
-     * accessible constructor.
-     * @param superclass class to extend or interface to implement
-     * @see #setInterfaces(Class[])
-     */
-    public void setSuperclass(Class superclass) {
-        if (superclass != null && superclass.isInterface()) {
-            setInterfaces(new Class[]{ superclass });
-        } else if (superclass != null && superclass.equals(Object.class)) {
-            // affects choice of ClassLoader
-            this.superclass = null;
-        } else {
-            this.superclass = superclass;
-        }
-    }
-
-    /**
-     * Set the interfaces to implement. The <code>Factory</code> interface will
-     * always be implemented regardless of what is specified here.
-     * @param interfaces array of interfaces to implement, or null
-     * @see Factory
-     */
-    public void setInterfaces(Class[] interfaces) {
-        this.interfaces = interfaces;
-    }
-
-    /**
-     * Set the {@link CallbackFilter} used to map the generated class' methods
-     * to a particular callback index.
-     * New object instances will always use the same mapping, but may use different
-     * actual callback objects.
-     * @param filter the callback filter to use when generating a new class
-     * @see #setCallbacks
-     */
-    public void setCallbackFilter(CallbackFilter filter) {
-        this.filter = filter;
-    }
-
-
-    /**
-     * Set the single {@link Callback} to use.
-     * Ignored if you use {@link #createClass}.
-     * @param callback the callback to use for all methods
-     * @see #setCallbacks
-     */
-    public void setCallback(final Callback callback) {
-        setCallbacks(new Callback[]{ callback });
-    }
-
-    /**
-     * Set the array of callbacks to use.
-     * Ignored if you use {@link #createClass}.
-     * You must use a {@link CallbackFilter} to specify the index into this
-     * array for each method in the proxied class.
-     * @param callbacks the callback array
-     * @see #setCallbackFilter
-     * @see #setCallback
-     */
-    public void setCallbacks(Callback[] callbacks) {
-        if (callbacks != null && callbacks.length == 0) {
-            throw new IllegalArgumentException("Array cannot be empty");
-        }
-        this.callbacks = callbacks;
-    }
-
-    /**
-     * Set whether the enhanced object instances should implement
-     * the {@link Factory} interface.
-     * This was added for tools that need for proxies to be more
-     * indistinguishable from their targets. Also, in some cases it may
-     * be necessary to disable the <code>Factory</code> interface to
-     * prevent code from changing the underlying callbacks.
-     * @param useFactory whether to implement <code>Factory</code>; default is <code>true</code>
-     */
-    public void setUseFactory(boolean useFactory) {
-        this.useFactory = useFactory;
-    }
-
-    /**
-     * Set whether methods called from within the proxy's constructer
-     * will be intercepted. The default value is true. Unintercepted methods
-     * will call the method of the proxy's base class, if it exists.
-     * @param interceptDuringConstruction whether to intercept methods called from the constructor
-     */
-    public void setInterceptDuringConstruction(boolean interceptDuringConstruction) {
-        this.interceptDuringConstruction = interceptDuringConstruction;
-    }
-
-    /**
-     * Set the single type of {@link Callback} to use.
-     * This may be used instead of {@link #setCallback} when calling
-     * {@link #createClass}, since it may not be possible to have
-     * an array of actual callback instances.
-     * @param callbackType the type of callback to use for all methods
-     * @see #setCallbackTypes
-     */     
-    public void setCallbackType(Class callbackType) {
-        setCallbackTypes(new Class[]{ callbackType });
-    }
-    
-    /**
-     * Set the array of callback types to use.
-     * This may be used instead of {@link #setCallbacks} when calling
-     * {@link #createClass}, since it may not be possible to have
-     * an array of actual callback instances.
-     * You must use a {@link CallbackFilter} to specify the index into this
-     * array for each method in the proxied class.
-     * @param callbackTypes the array of callback types
-     */
-    public void setCallbackTypes(Class[] callbackTypes) {
-        if (callbackTypes != null && callbackTypes.length == 0) {
-            throw new IllegalArgumentException("Array cannot be empty");
-        }
-        this.callbackTypes = CallbackInfo.determineTypes(callbackTypes);
-    }
-
-    /**
-     * Generate a new class if necessary and uses the specified
-     * callbacks (if any) to create a new object instance.
-     * Uses the no-arg constructor of the superclass.
-     * @return a new instance
-     */
-    public Object create() {
-        classOnly = false;
-        argumentTypes = null;
-        return createHelper();
-    }
-
-    /**
-     * Generate a new class if necessary and uses the specified
-     * callbacks (if any) to create a new object instance.
-     * Uses the constructor of the superclass matching the <code>argumentTypes</code>
-     * parameter, with the given arguments.
-     * @param argumentTypes constructor signature
-     * @param arguments compatible wrapped arguments to pass to constructor
-     * @return a new instance
-     */
-    public Object create(Class[] argumentTypes, Object[] arguments) {
-        classOnly = false;
-        if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) {
-            throw new IllegalArgumentException("Arguments must be non-null and of equal length");
-        }
-        this.argumentTypes = argumentTypes;
-        this.arguments = arguments;
-        return createHelper();
-    }
-
-    /**
-     * Generate a new class if necessary and return it without creating a new instance.
-     * This ignores any callbacks that have been set.
-     * To create a new instance you will have to use reflection, and methods
-     * called during the constructor will not be intercepted. To avoid this problem,
-     * use the multi-arg <code>create</code> method.
-     * @see #create(Class[], Object[])
-     */
-    public Class createClass() {
-        classOnly = true;
-        return (Class)createHelper();
-    }
-
-    /**
-     * Insert a static serialVersionUID field into the generated class.
-     * @param sUID the field value, or null to avoid generating field.
-     */
-    public void setSerialVersionUID(Long sUID) {
-        serialVersionUID = sUID;
-    }
-
-    private void validate() {
-        if (classOnly ^ (callbacks == null)) {
-            if (classOnly) {
-                throw new IllegalStateException("createClass does not accept callbacks");
-            } else {
-                throw new IllegalStateException("Callbacks are required");
-            }
-        }
-        if (classOnly && (callbackTypes == null)) {
-            throw new IllegalStateException("Callback types are required");
-        }
-        if (callbacks != null && callbackTypes != null) {
-            if (callbacks.length != callbackTypes.length) {
-                throw new IllegalStateException("Lengths of callback and callback types array must be the same");
-            }
-            Type[] check = CallbackInfo.determineTypes(callbacks);
-            for (int i = 0; i < check.length; i++) {
-                if (!check[i].equals(callbackTypes[i])) {
-                    throw new IllegalStateException("Callback " + check[i] + " is not assignable to " + callbackTypes[i]);
-                }
-            }
-        } else if (callbacks != null) {
-            callbackTypes = CallbackInfo.determineTypes(callbacks);
-        }
-        if (filter == null) {
-            if (callbackTypes.length > 1) {
-                throw new IllegalStateException("Multiple callback types possible but no filter specified");
-            }
-            filter = ALL_ZERO;
-        }
-        if (interfaces != null) {
-            for (int i = 0; i < interfaces.length; i++) {
-                if (interfaces[i] == null) {
-                    throw new IllegalStateException("Interfaces cannot be null");
-                }
-                if (!interfaces[i].isInterface()) {
-                    throw new IllegalStateException(interfaces[i] + " is not an interface");
-                }
-            }
-        }
-    }
-
-    private Object createHelper() {
-        validate();
-        if (superclass != null) {
-            setNamePrefix(superclass.getName());
-        } else if (interfaces != null) {
-            setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
-        }
-        return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
-                                                    ReflectUtils.getNames(interfaces),
-                                                    filter,
-                                                    callbackTypes,
-                                                    useFactory,
-                                                    interceptDuringConstruction,
-                                                    serialVersionUID));
-    }
-
-    protected ClassLoader getDefaultClassLoader() {
-        if (superclass != null) {
-            return superclass.getClassLoader();
-        } else if (interfaces != null) {
-            return interfaces[0].getClassLoader();
-        } else {
-            return null;
-        }
-    }
-
-    private Signature rename(Signature sig, int index) {
-        return new Signature("CGLIB$" + sig.getName() + "$" + index,
-                             sig.getDescriptor());
-    }
-    
-    /**
-     * Finds all of the methods that will be extended by an
-     * Enhancer-generated class using the specified superclass and
-     * interfaces. This can be useful in building a list of Callback
-     * objects. The methods are added to the end of the given list.  Due
-     * to the subclassing nature of the classes generated by Enhancer,
-     * the methods are guaranteed to be non-static, non-final, and
-     * non-private. Each method signature will only occur once, even if
-     * it occurs in multiple classes.
-     * @param superclass the class that will be extended, or null
-     * @param interfaces the list of interfaces that will be implemented, or null
-     * @param methods the list into which to copy the applicable methods
-     */
-    public static void getMethods(Class superclass, Class[] interfaces, List methods)
-    {
-        getMethods(superclass, interfaces, methods, null, null);
-    }
-
-    private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic)
-    {
-        ReflectUtils.addAllMethods(superclass, methods);
-        List target = (interfaceMethods != null) ? interfaceMethods : methods;
-        if (interfaces != null) {
-            for (int i = 0; i < interfaces.length; i++) {
-                if (interfaces[i] != Factory.class) {
-                    ReflectUtils.addAllMethods(interfaces[i], target);
-                }
-            }
-        }
-        if (interfaceMethods != null) {
-            if (forcePublic != null) {
-                forcePublic.addAll(MethodWrapper.createSet(interfaceMethods));
-            }
-            methods.addAll(interfaceMethods);
-        }
-        CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_STATIC));
-        CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true));
-        CollectionUtils.filter(methods, new DuplicatesPredicate());
-        CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_FINAL));
-    }
-
-    public void generateClass(ClassVisitor v) throws Exception {
-        Class sc = (superclass == null) ? Object.class : superclass;
-
-        if (TypeUtils.isFinal(sc.getModifiers()))
-            throw new IllegalArgumentException("Cannot subclass final class " + sc);
-        List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
-        filterConstructors(sc, constructors);
-
-        // Order is very important: must add superclass, then
-        // its superclass chain, then each interface and
-        // its superinterfaces.
-        List actualMethods = new ArrayList();
-        List interfaceMethods = new ArrayList();
-        final Set forcePublic = new HashSet();
-        getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
-
-        List methods = CollectionUtils.transform(actualMethods, new Transformer() {
-            public Object transform(Object value) {
-                Method method = (Method)value;
-                int modifiers = Constants.ACC_FINAL
-                    | (method.getModifiers()
-                       & ~Constants.ACC_ABSTRACT
-                       & ~Constants.ACC_NATIVE
-                       & ~Constants.ACC_SYNCHRONIZED);
-                if (forcePublic.contains(MethodWrapper.create(method))) {
-                    modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
-                }
-                return ReflectUtils.getMethodInfo(method, modifiers);
-            }
-        });
-
-        ClassEmitter e = new ClassEmitter(v);
-        e.begin_class(Constants.V1_2,
-                      Constants.ACC_PUBLIC,
-                      getClassName(),
-                      Type.getType(sc),
-                      (useFactory ?
-                       TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
-                       TypeUtils.getTypes(interfaces)),
-                      Constants.SOURCE_FILE);
-        List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
-
-        e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
-        if (!interceptDuringConstruction) {
-            e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
-        }
-        e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
-        e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
-        if (serialVersionUID != null) {
-            e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
-        }
-
-        for (int i = 0; i < callbackTypes.length; i++) {
-            e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
-        }
-
-        emitMethods(e, methods, actualMethods);
-        emitConstructors(e, constructorInfo);
-        emitSetThreadCallbacks(e);
-        emitSetStaticCallbacks(e);
-        emitBindCallbacks(e);
-
-        if (useFactory) {
-            int[] keys = getCallbackKeys();
-            emitNewInstanceCallbacks(e);
-            emitNewInstanceCallback(e);
-            emitNewInstanceMultiarg(e, constructorInfo);
-            emitGetCallback(e, keys);
-            emitSetCallback(e, keys);
-            emitGetCallbacks(e);
-            emitSetCallbacks(e);
-        }
-
-        e.end_class();
-    }
-
-    /**
-     * Filter the list of constructors from the superclass. The
-     * constructors which remain will be included in the generated
-     * class. The default implementation is to filter out all private
-     * constructors, but subclasses may extend Enhancer to override this
-     * behavior.
-     * @param sc the superclass
-     * @param constructors the list of all declared constructors from the superclass
-     * @throws IllegalArgumentException if there are no non-private constructors
-     */
-    protected void filterConstructors(Class sc, List constructors) {
-        CollectionUtils.filter(constructors, new VisibilityPredicate(sc, true));
-        if (constructors.size() == 0)
-            throw new IllegalArgumentException("No visible constructors in " + sc);
-    }
-
-    protected Object firstInstance(Class type) throws Exception {
-        if (classOnly) {
-            return type;
-        } else {
-            return createUsingReflection(type);
-        }
-    }
-
-    protected Object nextInstance(Object instance) {
-        Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass();
-        if (classOnly) {
-            return protoclass;
-        } else if (instance instanceof Factory) {
-            if (argumentTypes != null) {
-                return ((Factory)instance).newInstance(argumentTypes, arguments, callbacks);
-            } else {
-                return ((Factory)instance).newInstance(callbacks);
-            }
-        } else {
-            return createUsingReflection(protoclass);
-        }
-    }
-
-    /**
-     * Call this method to register the {@link Callback} array to use before
-     * creating a new instance of the generated class via reflection. If you are using
-     * an instance of <code>Enhancer</code> or the {@link Factory} interface to create
-     * new instances, this method is unnecessary. Its primary use is for when you want to
-     * cache and reuse a generated class yourself, and the generated class does
-     * <i>not</i> implement the {@link Factory} interface.
-     * <p>
-     * Note that this method only registers the callbacks on the current thread.
-     * If you want to register callbacks for instances created by multiple threads,
-     * use {@link #registerStaticCallbacks}.
-     * <p>
-     * The registered callbacks are overwritten and subsequently cleared
-     * when calling any of the <code>create</code> methods (such as
-     * {@link #create}), or any {@link Factory} <code>newInstance</code> method.
-     * Otherwise they are <i>not</i> cleared, and you should be careful to set them
-     * back to <code>null</code> after creating new instances via reflection if
-     * memory leakage is a concern.
-     * @param generatedClass a class previously created by {@link Enhancer}
-     * @param callbacks the array of callbacks to use when instances of the generated
-     * class are created
-     * @see #setUseFactory
-     */
-    public static void registerCallbacks(Class generatedClass, Callback[] callbacks) {
-        setThreadCallbacks(generatedClass, callbacks);
-    }
-
-    /**
-     * Similar to {@link #registerCallbacks}, but suitable for use
-     * when multiple threads will be creating instances of the generated class.
-     * The thread-level callbacks will always override the static callbacks.
-     * Static callbacks are never cleared.
-     * @param generatedClass a class previously created by {@link Enhancer}
-     * @param callbacks the array of callbacks to use when instances of the generated
-     * class are created
-     */
-    public static void registerStaticCallbacks(Class generatedClass, Callback[] callbacks) {
-        setCallbacksHelper(generatedClass, callbacks, SET_STATIC_CALLBACKS_NAME);
-    }
-
-    /**
-     * Determine if a class was generated using <code>Enhancer</code>.
-     * @param type any class
-     * @return whether the class was generated  using <code>Enhancer</code>
-     */
-    public static boolean isEnhanced(Class type) {
-        try {
-            getCallbacksSetter(type, SET_THREAD_CALLBACKS_NAME);
-            return true;
-        } catch (NoSuchMethodException e) {
-            return false;
-        }
-    }
-
-    private static void setThreadCallbacks(Class type, Callback[] callbacks) {
-        setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME);
-    }
-
-    private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName) {
-        // TODO: optimize
-        try {
-            Method setter = getCallbacksSetter(type, methodName);
-            setter.invoke(null, new Object[]{ callbacks });
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException(type + " is not an enhanced class");
-        } catch (IllegalAccessException e) {
-            throw new CodeGenerationException(e);
-        } catch (InvocationTargetException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-
-    private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException {
-        return type.getDeclaredMethod(methodName, new Class[]{ Callback[].class });
-    }
-
-    private Object createUsingReflection(Class type) {
-        setThreadCallbacks(type, callbacks);
-        try{
-        
-        if (argumentTypes != null) {
-        	
-             return ReflectUtils.newInstance(type, argumentTypes, arguments);
-             
-        } else {
-        	
-            return ReflectUtils.newInstance(type);
-            
-        }
-        }finally{
-         // clear thread callbacks to allow them to be gc'd
-         setThreadCallbacks(type, null);
-        }
-    }
-
-    /**
-     * Helper method to create an intercepted object.
-     * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
-     * instead of this static method.
-     * @param type class to extend or interface to implement
-     * @param callback the callback to use for all methods
-     */
-    public static Object create(Class type, Callback callback) {
-        Enhancer e = new Enhancer();
-        e.setSuperclass(type);
-        e.setCallback(callback);
-        return e.create();
-    }
-
-    /**
-     * Helper method to create an intercepted object.
-     * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
-     * instead of this static method.
-     * @param type class to extend or interface to implement
-     * @param interfaces array of interfaces to implement, or null
-     * @param callback the callback to use for all methods
-     */
-    public static Object create(Class superclass, Class interfaces[], Callback callback) {
-        Enhancer e = new Enhancer();
-        e.setSuperclass(superclass);
-        e.setInterfaces(interfaces);
-        e.setCallback(callback);
-        return e.create();
-    }
-
-    /**
-     * Helper method to create an intercepted object.
-     * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
-     * instead of this static method.
-     * @param type class to extend or interface to implement
-     * @param interfaces array of interfaces to implement, or null
-     * @param filter the callback filter to use when generating a new class
-     * @param callbacks callback implementations to use for the enhanced object
-     */
-    public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) {
-        Enhancer e = new Enhancer();
-        e.setSuperclass(superclass);
-        e.setInterfaces(interfaces);
-        e.setCallbackFilter(filter);
-        e.setCallbacks(callbacks);
-        return e.create();
-    }
-
-    private void emitConstructors(ClassEmitter ce, List constructors) {
-        boolean seenNull = false;
-        for (Iterator it = constructors.iterator(); it.hasNext();) {
-            MethodInfo constructor = (MethodInfo)it.next();
-            CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC);
-            e.load_this();
-            e.dup();
-            e.load_args();
-            Signature sig = constructor.getSignature();
-            seenNull = seenNull || sig.getDescriptor().equals("()V");
-            e.super_invoke_constructor(sig);
-            e.invoke_static_this(BIND_CALLBACKS);
-            if (!interceptDuringConstruction) {
-                e.load_this();
-                e.push(1);
-                e.putfield(CONSTRUCTED_FIELD);
-            }
-            e.return_value();
-            e.end_method();
-        }
-        if (!classOnly && !seenNull && arguments == null)
-            throw new IllegalArgumentException("Superclass has no null constructors but no arguments were given");
-    }
-
-    private int[] getCallbackKeys() {
-        int[] keys = new int[callbackTypes.length];
-        for (int i = 0; i < callbackTypes.length; i++) {
-            keys[i] = i;
-        }
-        return keys;
-    }
-
-    private void emitGetCallback(ClassEmitter ce, int[] keys) {
-        final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACK, null);
-        e.load_this();
-        e.invoke_static_this(BIND_CALLBACKS);
-        e.load_this();
-        e.load_arg(0);
-        e.process_switch(keys, new ProcessSwitchCallback() {
-            public void processCase(int key, Label end) {
-                e.getfield(getCallbackField(key));
-                e.goTo(end);
-            }
-            public void processDefault() {
-                e.pop(); // stack height
-                e.aconst_null();
-            }
-        });
-        e.return_value();
-        e.end_method();
-    }
-
-    private void emitSetCallback(ClassEmitter ce, int[] keys) {
-        final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null);
-        e.load_arg(0);
-        e.process_switch(keys, new ProcessSwitchCallback() {
-            public void processCase(int key, Label end) {
-                e.load_this();
-                e.load_arg(1);
-                e.checkcast(callbackTypes[key]);
-                e.putfield(getCallbackField(key));
-                e.goTo(end);
-            }
-            public void processDefault() {
-                // TODO: error?
-            }
-        });
-        e.return_value();
-        e.end_method();
-    }
-
-    private void emitSetCallbacks(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACKS, null);
-        e.load_this();
-        e.load_arg(0);
-        for (int i = 0; i < callbackTypes.length; i++) {
-            e.dup2();
-            e.aaload(i);
-            e.checkcast(callbackTypes[i]);
-            e.putfield(getCallbackField(i));
-        }
-        e.return_value();
-        e.end_method();
-    }
-
-    private void emitGetCallbacks(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACKS, null);
-        e.load_this();
-        e.invoke_static_this(BIND_CALLBACKS);
-        e.load_this();
-        e.push(callbackTypes.length);
-        e.newarray(CALLBACK);
-        for (int i = 0; i < callbackTypes.length; i++) {
-            e.dup();
-            e.push(i);
-            e.load_this();
-            e.getfield(getCallbackField(i));
-            e.aastore();
-        }
-        e.return_value();
-        e.end_method();
-    }
-
-    private void emitNewInstanceCallbacks(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
-        e.load_arg(0);
-        e.invoke_static_this(SET_THREAD_CALLBACKS);
-        emitCommonNewInstance(e);
-    }
-
-    private void emitCommonNewInstance(CodeEmitter e) {
-        e.new_instance_this();
-        e.dup();
-        e.invoke_constructor_this();
-        e.aconst_null();
-        e.invoke_static_this(SET_THREAD_CALLBACKS);
-        e.return_value();
-        e.end_method();
-    }
-    
-    private void emitNewInstanceCallback(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SINGLE_NEW_INSTANCE, null);
-        switch (callbackTypes.length) {
-        case 0:
-            // TODO: make sure Callback is null
-            break;
-        case 1:
-            // for now just make a new array; TODO: optimize
-            e.push(1);
-            e.newarray(CALLBACK);
-            e.dup();
-            e.push(0);
-            e.load_arg(0);
-            e.aastore();
-            e.invoke_static_this(SET_THREAD_CALLBACKS);
-            break;
-        default:
-            e.throw_exception(ILLEGAL_STATE_EXCEPTION, "More than one callback object required");
-        }
-        emitCommonNewInstance(e);
-    }
-
-    private void emitNewInstanceMultiarg(ClassEmitter ce, List constructors) {
-        final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null);
-        e.load_arg(2);
-        e.invoke_static_this(SET_THREAD_CALLBACKS);
-        e.new_instance_this();
-        e.dup();
-        e.load_arg(0);
-        EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                MethodInfo constructor = (MethodInfo)key;
-                Type types[] = constructor.getSignature().getArgumentTypes();
-                for (int i = 0; i < types.length; i++) {
-                    e.load_arg(1);
-                    e.push(i);
-                    e.aaload();
-                    e.unbox(types[i]);
-                }
-                e.invoke_constructor_this(constructor.getSignature());
-                e.goTo(end);
-            }
-            public void processDefault() {
-                e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found");
-            }
-        });
-        e.aconst_null();
-        e.invoke_static_this(SET_THREAD_CALLBACKS);
-        e.return_value();
-        e.end_method();
-    }
-
-    private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) {
-        CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes);
-
-        Map groups = new HashMap();
-        final Map indexes = new HashMap();
-        final Map originalModifiers = new HashMap();
-        final Map positions = CollectionUtils.getIndexMap(methods);
-
-        Iterator it1 = methods.iterator();
-        Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null;
-
-        while (it1.hasNext()) {
-            MethodInfo method = (MethodInfo)it1.next();
-            Method actualMethod = (it2 != null) ? (Method)it2.next() : null;
-            int index = filter.accept(actualMethod, actualMethods);
-            if (index >= callbackTypes.length) {
-                throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);
-            }
-            originalModifiers.put(method, new Integer((actualMethod != null) ? actualMethod.getModifiers() : method.getModifiers()));
-            indexes.put(method, new Integer(index));
-            List group = (List)groups.get(generators[index]);
-            if (group == null) {
-                groups.put(generators[index], group = new ArrayList(methods.size()));
-            }
-            group.add(method);
-        }
-
-        Set seenGen = new HashSet();
-        CodeEmitter se = ce.getStaticHook();
-        se.new_instance(THREAD_LOCAL);
-        se.dup();
-        se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);
-        se.putfield(THREAD_CALLBACKS_FIELD);
-
-        final Object[] state = new Object[1];
-        CallbackGenerator.Context context = new CallbackGenerator.Context() {
-            public ClassLoader getClassLoader() {
-                return Enhancer.this.getClassLoader();
-            }
-            public int getOriginalModifiers(MethodInfo method) {
-                return ((Integer)originalModifiers.get(method)).intValue();
-            }
-            public int getIndex(MethodInfo method) {
-                return ((Integer)indexes.get(method)).intValue();
-            }
-            public void emitCallback(CodeEmitter e, int index) {
-                emitCurrentCallback(e, index);
-            }
-            public Signature getImplSignature(MethodInfo method) {
-                return rename(method.getSignature(), ((Integer)positions.get(method)).intValue());
-            }
-            public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) {
-                CodeEmitter e = EmitUtils.begin_method(ce, method);
-                if (!interceptDuringConstruction &&
-                    !TypeUtils.isAbstract(method.getModifiers())) {
-                    Label constructed = e.make_label();
-                    e.load_this();
-                    e.getfield(CONSTRUCTED_FIELD);
-                    e.if_jump(e.NE, constructed);
-                    e.load_this();
-                    e.load_args();
-                    e.super_invoke();
-                    e.return_value();
-                    e.mark(constructed);
-                }
-                return e;
-            }
-        };
-        for (int i = 0; i < callbackTypes.length; i++) {
-            CallbackGenerator gen = generators[i];
-            if (!seenGen.contains(gen)) {
-                seenGen.add(gen);
-                final List fmethods = (List)groups.get(gen);
-                if (fmethods != null) {
-                    try {
-                        gen.generate(ce, context, fmethods);
-                        gen.generateStatic(se, context, fmethods);
-                    } catch (RuntimeException x) {
-                        throw x;
-                    } catch (Exception x) {
-                        throw new CodeGenerationException(x);
-                    }
-                }
-            }
-        }
-        se.return_value();
-        se.end_method();
-    }
-
-    private void emitSetThreadCallbacks(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
-                                        SET_THREAD_CALLBACKS,
-                                        null);
-        e.getfield(THREAD_CALLBACKS_FIELD);
-        e.load_arg(0);
-        e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET);
-        e.return_value();
-        e.end_method();
-    }
-
-    private void emitSetStaticCallbacks(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
-                                        SET_STATIC_CALLBACKS,
-                                        null);
-        e.load_arg(0);
-        e.putfield(STATIC_CALLBACKS_FIELD);
-        e.return_value();
-        e.end_method();
-    }
-    
-    private void emitCurrentCallback(CodeEmitter e, int index) {
-        e.load_this();
-        e.getfield(getCallbackField(index));
-        e.dup();
-        Label end = e.make_label();
-        e.ifnonnull(end);
-        e.pop(); // stack height
-        e.load_this();
-        e.invoke_static_this(BIND_CALLBACKS);
-        e.load_this();
-        e.getfield(getCallbackField(index));
-        e.mark(end);
-    }
-
-    private void emitBindCallbacks(ClassEmitter ce) {
-        CodeEmitter e = ce.begin_method(Constants.PRIVATE_FINAL_STATIC,
-                                        BIND_CALLBACKS,
-                                        null);
-        Local me = e.make_local();
-        e.load_arg(0);
-        e.checkcast_this();
-        e.store_local(me);
-
-        Label end = e.make_label();
-        e.load_local(me);
-        e.getfield(BOUND_FIELD);
-        e.if_jump(e.NE, end);
-        e.load_local(me);
-        e.push(1);
-        e.putfield(BOUND_FIELD);
-
-        e.getfield(THREAD_CALLBACKS_FIELD);
-        e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET);
-        e.dup();
-        Label found_callback = e.make_label();
-        e.ifnonnull(found_callback);
-        e.pop();
-
-        e.getfield(STATIC_CALLBACKS_FIELD);
-        e.dup();
-        e.ifnonnull(found_callback);
-        e.pop();
-        e.goTo(end);
-
-        e.mark(found_callback);
-        e.checkcast(CALLBACK_ARRAY);
-        e.load_local(me);
-        e.swap();
-        for (int i = callbackTypes.length - 1; i >= 0; i--) {
-            if (i != 0) {
-                e.dup2();
-            }
-            e.aaload(i);
-            e.checkcast(callbackTypes[i]);
-            e.putfield(getCallbackField(i));
-        }
-
-        e.mark(end);
-        e.return_value();
-        e.end_method();
-    }
-
-    private static String getCallbackField(int index) {
-        return "CGLIB$CALLBACK_" + index;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/Factory.java b/cglib-and-asm/src/org/mockito/cglib/proxy/Factory.java
deleted file mode 100644
index 033a5fe..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/Factory.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2002,2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.mockito.cglib.proxy;
-
-/**
- * All enhanced instances returned by the {@link Enhancer} class implement this interface.
- * Using this interface for new instances is faster than going through the <code>Enhancer</code>
- * interface or using reflection. In addition, to intercept methods called during
- * object construction you <b>must</b> use these methods instead of reflection.
- * @author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">baliuka@mwm.lt</a>
- * @version $Id: Factory.java,v 1.13 2004/06/24 21:15:20 herbyderby Exp $
- */
-public interface Factory {
-    /**
-     * Creates new instance of the same type, using the no-arg constructor.
-     * The class of this object must have been created using a single Callback type.
-     * If multiple callbacks are required an exception will be thrown.
-     * @param callback the new interceptor to use
-     * @return new instance of the same type
-     */     
-    Object newInstance(Callback callback);
-    
-    /**
-     * Creates new instance of the same type, using the no-arg constructor.
-     * @param callbacks the new callbacks(s) to use
-     * @return new instance of the same type
-     */     
-    Object newInstance(Callback[] callbacks);
-
-    /**
-     * Creates a new instance of the same type, using the constructor
-     * matching the given signature.
-     * @param types the constructor argument types
-     * @param args the constructor arguments
-     * @param callbacks the new interceptor(s) to use
-     * @return new instance of the same type
-     */
-    Object newInstance(Class[] types, Object[] args, Callback[] callbacks);
-
-    /**
-     * Return the <code>Callback</code> implementation at the specified index.
-     * @param index the callback index
-     * @return the callback implementation
-     */
-    Callback getCallback(int index);
-
-    /**
-     * Set the callback for this object for the given type.
-     * @param index the callback index to replace
-     * @param callback the new callback
-     */
-    void setCallback(int index, Callback callback);
-
-    /**
-     * Replace all of the callbacks for this object at once.
-     * @param callbacks the new callbacks(s) to use
-     */
-    void setCallbacks(Callback[] callbacks);
-
-    /**
-     * Get the current set of callbacks for ths object.
-     * @return a new array instance
-     */     
-    Callback[] getCallbacks();
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/FixedValue.java b/cglib-and-asm/src/org/mockito/cglib/proxy/FixedValue.java
deleted file mode 100644
index 03cc0b3..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/FixedValue.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * {@link Enhancer} callback that simply returns the value to return
- * from the proxied method. No information about what method
- * is being called is available to the callback, and the type of
- * the returned object must be compatible with the return type of
- * the proxied method. This makes this callback primarily useful
- * for forcing a particular method (through the use of a {@link CallbackFilter}
- * to return a fixed value with little overhead.
- */
-public interface FixedValue extends Callback {
-    /**
-     * Return the object which the original method invocation should
-     * return. This method is called for <b>every</b> method invocation.
-     * @return an object matching the type of the return value for every
-     * method this callback is mapped to
-     */
-    Object loadObject() throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/FixedValueGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/FixedValueGenerator.java
deleted file mode 100644
index 5542b0d..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/FixedValueGenerator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.util.*;
-
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class FixedValueGenerator implements CallbackGenerator {
-    public static final FixedValueGenerator INSTANCE = new FixedValueGenerator();
-    private static final Type FIXED_VALUE =
-      TypeUtils.parseType("org.mockito.cglib.proxy.FixedValue");
-    private static final Signature LOAD_OBJECT =
-      TypeUtils.parseSignature("Object loadObject()");
-
-    public void generate(ClassEmitter ce, Context context, List methods) {
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            CodeEmitter e = context.beginMethod(ce, method);
-            context.emitCallback(e, context.getIndex(method));
-            e.invoke_interface(FIXED_VALUE, LOAD_OBJECT);
-            e.unbox_or_zero(e.getReturnType());
-            e.return_value();
-            e.end_method();
-        }
-    }
-
-    public void generateStatic(CodeEmitter e, Context context, List methods) { }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/InterfaceMaker.java b/cglib-and-asm/src/org/mockito/cglib/proxy/InterfaceMaker.java
deleted file mode 100644
index 67627fe..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/InterfaceMaker.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * Generates new interfaces at runtime.
- * By passing a generated interface to the Enhancer's list of interfaces to
- * implement, you can make your enhanced classes handle an arbitrary set
- * of method signatures.
- * @author Chris Nokleberg
- * @version $Id: InterfaceMaker.java,v 1.4 2006/03/05 02:43:19 herbyderby Exp $
- */
-public class InterfaceMaker extends AbstractClassGenerator
-{
-    private static final Source SOURCE = new Source(InterfaceMaker.class.getName());
-    private Map signatures = new HashMap();
-
-    /**
-     * Create a new <code>InterfaceMaker</code>. A new <code>InterfaceMaker</code>
-     * object should be used for each generated interface, and should not
-     * be shared across threads.
-     */
-    public InterfaceMaker() {
-        super(SOURCE);
-    }
-
-    /**
-     * Add a method signature to the interface.
-     * @param sig the method signature to add to the interface
-     * @param exceptions an array of exception types to declare for the method
-     */
-    public void add(Signature sig, Type[] exceptions) {
-        signatures.put(sig, exceptions);
-    }
-
-    /**
-     * Add a method signature to the interface. The method modifiers are ignored,
-     * since interface methods are by definition abstract and public.
-     * @param method the method to add to the interface
-     */
-    public void add(Method method) {
-        add(ReflectUtils.getSignature(method),
-            ReflectUtils.getExceptionTypes(method));
-    }
-
-    /**
-     * Add all the public methods in the specified class.
-     * Methods from superclasses are included, except for methods declared in the base
-     * Object class (e.g. <code>getClass</code>, <code>equals</code>, <code>hashCode</code>).
-     * @param class the class containing the methods to add to the interface
-     */
-    public void add(Class clazz) {
-        Method[] methods = clazz.getMethods();
-        for (int i = 0; i < methods.length; i++) {
-            Method m = methods[i];
-            if (!m.getDeclaringClass().getName().equals("java.lang.Object")) {
-                add(m);
-            }
-        }
-    }
-
-    /**
-     * Create an interface using the current set of method signatures.
-     */
-    public Class create() {
-        setUseCache(false);
-        return (Class)super.create(this);
-    }
-
-    protected ClassLoader getDefaultClassLoader() {
-        return null;
-    }
-    
-    protected Object firstInstance(Class type) {
-        return type;
-    }
-
-    protected Object nextInstance(Object instance) {
-        throw new IllegalStateException("InterfaceMaker does not cache");
-    }
-
-    public void generateClass(ClassVisitor v) throws Exception {
-        ClassEmitter ce = new ClassEmitter(v);
-        ce.begin_class(Constants.V1_2,
-                       Constants.ACC_PUBLIC | Constants.ACC_INTERFACE,
-                       getClassName(),
-                       null,
-                       null,
-                       Constants.SOURCE_FILE);
-        for (Iterator it = signatures.keySet().iterator(); it.hasNext();) {
-            Signature sig = (Signature)it.next();
-            Type[] exceptions = (Type[])signatures.get(sig);
-            ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT,
-                            sig,
-                            exceptions).end_method();
-        }
-        ce.end_class();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/InvocationHandler.java b/cglib-and-asm/src/org/mockito/cglib/proxy/InvocationHandler.java
deleted file mode 100644
index 86314bb..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/InvocationHandler.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-
-/**
- * {@link java.lang.reflect.InvocationHandler} replacement (unavailable under JDK 1.2).
- * This callback type is primarily for use by the {@link Proxy} class but
- * may be used with {@link Enhancer} as well.
- * @author Neeme Praks <a href="mailto:neeme@apache.org">neeme@apache.org</a>
- * @version $Id: InvocationHandler.java,v 1.3 2004/06/24 21:15:20 herbyderby Exp $
- */
-public interface InvocationHandler
-extends Callback
-{
-    /**
-     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
-     */
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
-
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/InvocationHandlerGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/InvocationHandlerGenerator.java
deleted file mode 100644
index bb40631..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/InvocationHandlerGenerator.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.util.*;
-
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class InvocationHandlerGenerator
-implements CallbackGenerator
-{
-    public static final InvocationHandlerGenerator INSTANCE = new InvocationHandlerGenerator();
-
-    private static final Type INVOCATION_HANDLER =
-      TypeUtils.parseType("org.mockito.cglib.proxy.InvocationHandler");
-    private static final Type UNDECLARED_THROWABLE_EXCEPTION =
-      TypeUtils.parseType("org.mockito.cglib.proxy.UndeclaredThrowableException");
-    private static final Type METHOD =
-      TypeUtils.parseType("java.lang.reflect.Method");
-    private static final Signature INVOKE =
-      TypeUtils.parseSignature("Object invoke(Object, java.lang.reflect.Method, Object[])");
-
-    public void generate(ClassEmitter ce, Context context, List methods) {
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            Signature impl = context.getImplSignature(method);
-            ce.declare_field(Constants.PRIVATE_FINAL_STATIC, impl.getName(), METHOD, null);
-
-            CodeEmitter e = context.beginMethod(ce, method);
-            Block handler = e.begin_block();
-            context.emitCallback(e, context.getIndex(method));
-            e.load_this();
-            e.getfield(impl.getName());
-            e.create_arg_array();
-            e.invoke_interface(INVOCATION_HANDLER, INVOKE);
-            e.unbox(method.getSignature().getReturnType());
-            e.return_value();
-            handler.end();
-            EmitUtils.wrap_undeclared_throwable(e, handler, method.getExceptionTypes(), UNDECLARED_THROWABLE_EXCEPTION);
-            e.end_method();
-        }
-    }
-
-    public void generateStatic(CodeEmitter e, Context context, List methods) {
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            EmitUtils.load_method(e, method);
-            e.putfield(context.getImplSignature(method).getName());
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/LazyLoader.java b/cglib-and-asm/src/org/mockito/cglib/proxy/LazyLoader.java
deleted file mode 100644
index 35cc261..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/LazyLoader.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * Lazy-loading {@link Enhancer} callback.
- */
-public interface LazyLoader extends Callback {
-    /**
-     * Return the object which the original method invocation should be
-     * dispatched. Called as soon as the first lazily-loaded method in
-     * the enhanced instance is invoked. The same object is then used
-     * for every future method call to the proxy instance.
-     * @return an object that can invoke the method
-     */
-    Object loadObject() throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/LazyLoaderGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/LazyLoaderGenerator.java
deleted file mode 100644
index a5b68b0..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/LazyLoaderGenerator.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.util.*;
-
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class LazyLoaderGenerator implements CallbackGenerator {
-    public static final LazyLoaderGenerator INSTANCE = new LazyLoaderGenerator();
-
-    private static final Signature LOAD_OBJECT = 
-      TypeUtils.parseSignature("Object loadObject()");
-    private static final Type LAZY_LOADER =
-      TypeUtils.parseType("org.mockito.cglib.proxy.LazyLoader");
-
-    public void generate(ClassEmitter ce, Context context, List methods) {
-        Set indexes = new HashSet();
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            if (TypeUtils.isProtected(method.getModifiers())) {
-                // ignore protected methods
-            } else {
-                int index = context.getIndex(method);
-                indexes.add(new Integer(index));
-                CodeEmitter e = context.beginMethod(ce, method);
-                e.load_this();
-                e.dup();
-                e.invoke_virtual_this(loadMethod(index));
-                e.checkcast(method.getClassInfo().getType());
-                e.load_args();
-                e.invoke(method);
-                e.return_value();
-                e.end_method();
-            }
-        }
-
-        for (Iterator it = indexes.iterator(); it.hasNext();) {
-            int index = ((Integer)it.next()).intValue();
-
-            String delegate = "CGLIB$LAZY_LOADER_" + index;
-            ce.declare_field(Constants.ACC_PRIVATE, delegate, Constants.TYPE_OBJECT, null);
-
-            CodeEmitter e = ce.begin_method(Constants.ACC_PRIVATE |
-                                            Constants.ACC_SYNCHRONIZED |
-                                            Constants.ACC_FINAL,
-                                            loadMethod(index),
-                                            null);
-            e.load_this();
-            e.getfield(delegate);
-            e.dup();
-            Label end = e.make_label();
-            e.ifnonnull(end);
-            e.pop();
-            e.load_this();
-            context.emitCallback(e, index);
-            e.invoke_interface(LAZY_LOADER, LOAD_OBJECT);
-            e.dup_x1();
-            e.putfield(delegate);
-            e.mark(end);
-            e.return_value();
-            e.end_method();
-            
-        }
-    }
-
-    private Signature loadMethod(int index) {
-        return new Signature("CGLIB$LOAD_PRIVATE_" + index,
-                             Constants.TYPE_OBJECT,
-                             Constants.TYPES_EMPTY);
-    }
-
-    public void generateStatic(CodeEmitter e, Context context, List methods) { }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/MethodInterceptor.java b/cglib-and-asm/src/org/mockito/cglib/proxy/MethodInterceptor.java
deleted file mode 100644
index 749dcf2..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/MethodInterceptor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2002,2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * General-purpose {@link Enhancer} callback which provides for "around advice".
- * @author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">baliuka@mwm.lt</a>
- * @version $Id: MethodInterceptor.java,v 1.8 2004/06/24 21:15:20 herbyderby Exp $
- */
-public interface MethodInterceptor
-extends Callback
-{
-    /**
-     * All generated proxied methods call this method instead of the original method.
-     * The original method may either be invoked by normal reflection using the Method object,
-     * or by using the MethodProxy (faster).
-     * @param obj "this", the enhanced object
-     * @param method intercepted Method
-     * @param args argument array; primitive types are wrapped
-     * @param proxy used to invoke super (non-intercepted method); may be called
-     * as many times as needed
-     * @throws Throwable any exception may be thrown; if so, super method will not be invoked
-     * @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
-     * @see MethodProxy
-     */    
-    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
-                               MethodProxy proxy) throws Throwable;
-
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/MethodInterceptorGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/MethodInterceptorGenerator.java
deleted file mode 100644
index 12e33de..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/MethodInterceptorGenerator.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-import java.util.*;
-
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class MethodInterceptorGenerator
-implements CallbackGenerator
-{
-    public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator();
-
-    static final String EMPTY_ARGS_NAME = "CGLIB$emptyArgs";
-    static final String FIND_PROXY_NAME = "CGLIB$findMethodProxy";
-    static final Class[] FIND_PROXY_TYPES = { Signature.class };
-
-    private static final Type ABSTRACT_METHOD_ERROR =
-      TypeUtils.parseType("AbstractMethodError");
-    private static final Type METHOD =
-      TypeUtils.parseType("java.lang.reflect.Method");
-    private static final Type REFLECT_UTILS =
-      TypeUtils.parseType("org.mockito.cglib.core.ReflectUtils");
-    private static final Type METHOD_PROXY =
-      TypeUtils.parseType("org.mockito.cglib.proxy.MethodProxy");
-    private static final Type METHOD_INTERCEPTOR =
-      TypeUtils.parseType("org.mockito.cglib.proxy.MethodInterceptor");
-    private static final Signature GET_DECLARED_METHODS =
-      TypeUtils.parseSignature("java.lang.reflect.Method[] getDeclaredMethods()");
-    private static final Signature GET_DECLARING_CLASS =
-      TypeUtils.parseSignature("Class getDeclaringClass()");
-    private static final Signature FIND_METHODS =
-      TypeUtils.parseSignature("java.lang.reflect.Method[] findMethods(String[], java.lang.reflect.Method[])");
-    private static final Signature MAKE_PROXY =
-      new Signature("create", METHOD_PROXY, new Type[]{
-          Constants.TYPE_CLASS,
-          Constants.TYPE_CLASS,
-          Constants.TYPE_STRING,
-          Constants.TYPE_STRING,
-          Constants.TYPE_STRING
-      });
-    private static final Signature INTERCEPT =
-      new Signature("intercept", Constants.TYPE_OBJECT, new Type[]{
-          Constants.TYPE_OBJECT,
-          METHOD,
-          Constants.TYPE_OBJECT_ARRAY,
-          METHOD_PROXY
-      });
-    private static final Signature FIND_PROXY =
-      new Signature(FIND_PROXY_NAME, METHOD_PROXY, new Type[]{ Constants.TYPE_SIGNATURE });
-    private static final Signature TO_STRING =
-      TypeUtils.parseSignature("String toString()");
-    private static final Transformer METHOD_TO_CLASS = new Transformer(){
-        public Object transform(Object value) {
-            return ((MethodInfo)value).getClassInfo();
-        }
-    };
-    private static final Signature CSTRUCT_SIGNATURE =
-        TypeUtils.parseConstructor("String, String");
-
-    private String getMethodField(Signature impl) {
-        return impl.getName() + "$Method";
-    }
-    private String getMethodProxyField(Signature impl) {
-        return impl.getName() + "$Proxy";
-    }
-
-    public void generate(ClassEmitter ce, Context context, List methods) {
-        Map sigMap = new HashMap();
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            Signature sig = method.getSignature();
-            Signature impl = context.getImplSignature(method);
-
-            String methodField = getMethodField(impl);
-            String methodProxyField = getMethodProxyField(impl);
-
-            sigMap.put(sig.toString(), methodProxyField);
-            ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodField, METHOD, null);
-            ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodProxyField, METHOD_PROXY, null);
-            ce.declare_field(Constants.PRIVATE_FINAL_STATIC, EMPTY_ARGS_NAME, Constants.TYPE_OBJECT_ARRAY, null);
-            CodeEmitter e;
-
-            // access method
-            e = ce.begin_method(Constants.ACC_FINAL,
-                                impl,
-                                method.getExceptionTypes());
-            superHelper(e, method);
-            e.return_value();
-            e.end_method();
-
-            // around method
-            e = context.beginMethod(ce, method);
-            Label nullInterceptor = e.make_label();
-            context.emitCallback(e, context.getIndex(method));
-            e.dup();
-            e.ifnull(nullInterceptor);
-
-            e.load_this();
-            e.getfield(methodField);
-            
-            if (sig.getArgumentTypes().length == 0) {
-                e.getfield(EMPTY_ARGS_NAME);
-            } else {
-                e.create_arg_array();
-            }
-            
-            e.getfield(methodProxyField);
-            e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT);
-            e.unbox_or_zero(sig.getReturnType());
-            e.return_value();
-
-            e.mark(nullInterceptor);
-            superHelper(e, method);
-            e.return_value();
-            e.end_method();
-        }
-        generateFindProxy(ce, sigMap);
-    }
-
-    private static void superHelper(CodeEmitter e, MethodInfo method)
-    {
-        if (TypeUtils.isAbstract(method.getModifiers())) {
-            e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" );
-        } else {
-            e.load_this();
-            e.load_args();
-            e.super_invoke(method.getSignature());
-        }
-    }
-
-    public void generateStatic(CodeEmitter e, Context context, List methods) throws Exception {
-        /* generates:
-           static {
-             Class thisClass = Class.forName("NameOfThisClass");
-             Class cls = Class.forName("java.lang.Object");
-             String[] sigs = new String[]{ "toString", "()Ljava/lang/String;", ... };
-             Method[] methods = cls.getDeclaredMethods();
-             methods = ReflectUtils.findMethods(sigs, methods);
-             METHOD_0 = methods[0];
-             CGLIB$ACCESS_0 = MethodProxy.create(cls, thisClass, "()Ljava/lang/String;", "toString", "CGLIB$ACCESS_0");
-             ...
-           }
-        */
-
-        e.push(0);
-        e.newarray();
-        e.putfield(EMPTY_ARGS_NAME);
-
-        Local thisclass = e.make_local();
-        Local declaringclass = e.make_local();
-        EmitUtils.load_class_this(e);
-        e.store_local(thisclass);
-        
-        Map methodsByClass = CollectionUtils.bucket(methods, METHOD_TO_CLASS);
-        for (Iterator i = methodsByClass.keySet().iterator(); i.hasNext();) {
-            ClassInfo classInfo = (ClassInfo)i.next();
-
-            List classMethods = (List)methodsByClass.get(classInfo);
-            e.push(2 * classMethods.size());
-            e.newarray(Constants.TYPE_STRING);
-            for (int index = 0; index < classMethods.size(); index++) {
-                MethodInfo method = (MethodInfo)classMethods.get(index);
-                Signature sig = method.getSignature();
-                e.dup();
-                e.push(2 * index);
-                e.push(sig.getName());
-                e.aastore();
-                e.dup();
-                e.push(2 * index + 1);
-                e.push(sig.getDescriptor());
-                e.aastore();
-            }
-            
-            EmitUtils.load_class(e, classInfo.getType());
-            e.dup();
-            e.store_local(declaringclass);
-            e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHODS);
-            e.invoke_static(REFLECT_UTILS, FIND_METHODS);
-
-            for (int index = 0; index < classMethods.size(); index++) {
-                MethodInfo method = (MethodInfo)classMethods.get(index);
-                Signature sig = method.getSignature();
-                Signature impl = context.getImplSignature(method);
-                e.dup();
-                e.push(index);
-                e.array_load(METHOD);
-                e.putfield(getMethodField(impl));
-
-                e.load_local(declaringclass);
-                e.load_local(thisclass);
-                e.push(sig.getDescriptor());
-                e.push(sig.getName());
-                e.push(impl.getName());
-                e.invoke_static(METHOD_PROXY, MAKE_PROXY);
-                e.putfield(getMethodProxyField(impl));
-            }
-            e.pop();
-        }
-    }
-
-    public void generateFindProxy(ClassEmitter ce, final Map sigMap) {
-        final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
-                                              FIND_PROXY,
-                                              null);
-        e.load_arg(0);
-        e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
-        ObjectSwitchCallback callback = new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                e.getfield((String)sigMap.get(key));
-                e.return_value();
-            }
-            public void processDefault() {
-                e.aconst_null();
-                e.return_value();
-            }
-        };
-        EmitUtils.string_switch(e,
-                                (String[])sigMap.keySet().toArray(new String[0]),
-                                Constants.SWITCH_STYLE_HASH,
-                                callback);
-        e.end_method();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/MethodProxy.java b/cglib-and-asm/src/org/mockito/cglib/proxy/MethodProxy.java
deleted file mode 100644
index 2e9a65f..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/MethodProxy.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import org.mockito.cglib.core.AbstractClassGenerator;
-import org.mockito.cglib.core.CodeGenerationException;
-import org.mockito.cglib.core.GeneratorStrategy;
-import org.mockito.cglib.core.NamingPolicy;
-import org.mockito.cglib.core.Signature;
-import org.mockito.cglib.reflect.FastClass;
-
-
-/**
- * Classes generated by {@link Enhancer} pass this object to the
- * registered {@link MethodInterceptor} objects when an intercepted method is invoked. It can
- * be used to either invoke the original method, or call the same method on a different
- * object of the same type.
- * @version $Id: MethodProxy.java,v 1.14 2008/05/26 04:05:50 herbyderby Exp $
- */
-public class MethodProxy {
-    private Signature sig1;
-    private Signature sig2;
-    private CreateInfo createInfo;
-    
-    private final Object initLock = new Object();
-    private volatile FastClassInfo fastClassInfo;
-    
-    /**
-     * For internal use by {@link Enhancer} only; see the {@link org.mockito.cglib.reflect.FastMethod} class
-     * for similar functionality.
-     */
-    public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
-        MethodProxy proxy = new MethodProxy();
-        proxy.sig1 = new Signature(name1, desc);
-        proxy.sig2 = new Signature(name2, desc);
-        proxy.createInfo = new CreateInfo(c1, c2);
-        return proxy;
-    }
-
-    private void init()
-    {
-        /* 
-         * Using a volatile invariant allows us to initialize the FastClass and
-         * method index pairs atomically.
-         * 
-         * Double-checked locking is safe with volatile in Java 5.  Before 1.5 this 
-         * code could allow fastClassInfo to be instantiated more than once, which
-         * appears to be benign.
-         */
-        if (fastClassInfo == null)
-        {
-            synchronized (initLock)
-            {
-                if (fastClassInfo == null)
-                {
-                    CreateInfo ci = createInfo;
-
-                    FastClassInfo fci = new FastClassInfo();
-                    fci.f1 = helper(ci, ci.c1);
-                    fci.f2 = helper(ci, ci.c2);
-                    fci.i1 = fci.f1.getIndex(sig1);
-                    fci.i2 = fci.f2.getIndex(sig2);
-                    fastClassInfo = fci;
-                }
-            }
-        }
-    }
-
-    private static class FastClassInfo
-    {
-        FastClass f1;
-        FastClass f2;
-        int i1;
-        int i2;
-    }
-
-    private static class CreateInfo
-    {
-        Class c1;
-        Class c2;
-        NamingPolicy namingPolicy;
-        GeneratorStrategy strategy;
-        boolean attemptLoad;
-        
-        public CreateInfo(Class c1, Class c2)
-        {
-            this.c1 = c1;
-            this.c2 = c2;
-            AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
-            if (fromEnhancer != null) {
-                namingPolicy = fromEnhancer.getNamingPolicy();
-                strategy = fromEnhancer.getStrategy();
-                attemptLoad = fromEnhancer.getAttemptLoad();
-            }
-        }
-    }
-
-    private static FastClass helper(CreateInfo ci, Class type) {
-        FastClass.Generator g = new FastClass.Generator();
-        g.setType(type);
-        g.setClassLoader(ci.c2.getClassLoader());
-        g.setNamingPolicy(ci.namingPolicy);
-        g.setStrategy(ci.strategy);
-        g.setAttemptLoad(ci.attemptLoad);
-        return g.create();
-    }
-
-    private MethodProxy() {
-    }
-
-    /**
-     * Return the signature of the proxied method.
-     */
-    public Signature getSignature() {
-        return sig1;
-    }
-
-    /**
-     * Return the name of the synthetic method created by CGLIB which is
-     * used by {@link #invokeSuper} to invoke the superclass
-     * (non-intercepted) method implementation. The parameter types are
-     * the same as the proxied method.
-     */
-    public String getSuperName() {
-        return sig2.getName();
-    }
-
-    /**
-     * Return the {@link org.mockito.cglib.reflect.FastClass} method index
-     * for the method used by {@link #invokeSuper}. This index uniquely
-     * identifies the method within the generated proxy, and therefore
-     * can be useful to reference external metadata.
-     * @see #getSuperName
-     */
-    public int getSuperIndex() {
-        init();
-        return fastClassInfo.i2;
-    }
-
-    /**
-     * Return the <code>MethodProxy</code> used when intercepting the method
-     * matching the given signature.
-     * @param type the class generated by Enhancer
-     * @param sig the signature to match
-     * @return the MethodProxy instance, or null if no applicable matching method is found
-     * @throws IllegalArgumentException if the Class was not created by Enhancer or does not use a MethodInterceptor
-     */
-    public static MethodProxy find(Class type, Signature sig) {
-        try {
-            Method m = type.getDeclaredMethod(MethodInterceptorGenerator.FIND_PROXY_NAME,
-                                              MethodInterceptorGenerator.FIND_PROXY_TYPES);
-            return (MethodProxy)m.invoke(null, new Object[]{ sig });
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("Class " + type + " does not use a MethodInterceptor");
-        } catch (IllegalAccessException e) {
-            throw new CodeGenerationException(e);
-        } catch (InvocationTargetException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-
-    /**
-     * Invoke the original method, on a different object of the same type.
-     * @param obj the compatible object; recursion will result if you use the object passed as the first
-     * argument to the MethodInterceptor (usually not what you want)
-     * @param args the arguments passed to the intercepted method; you may substitute a different
-     * argument array as long as the types are compatible
-     * @see MethodInterceptor#intercept
-     * @throws Throwable the bare exceptions thrown by the called method are passed through
-     * without wrapping in an <code>InvocationTargetException</code>
-     */
-    public Object invoke(Object obj, Object[] args) throws Throwable {
-        try {
-            init();
-            FastClassInfo fci = fastClassInfo;
-            return fci.f1.invoke(fci.i1, obj, args);
-        } catch (InvocationTargetException e) {
-            throw e.getTargetException();
-        } catch (IllegalArgumentException e) {
-            if (fastClassInfo.i1 < 0)
-                throw new IllegalArgumentException("Protected method: " + sig1);
-            throw e;
-        }
-    }
-
-    /**
-     * Invoke the original (super) method on the specified object.
-     * @param obj the enhanced object, must be the object passed as the first
-     * argument to the MethodInterceptor
-     * @param args the arguments passed to the intercepted method; you may substitute a different
-     * argument array as long as the types are compatible
-     * @see MethodInterceptor#intercept
-     * @throws Throwable the bare exceptions thrown by the called method are passed through
-     * without wrapping in an <code>InvocationTargetException</code>
-     */
-    public Object invokeSuper(Object obj, Object[] args) throws Throwable {
-        try {
-            init();
-            FastClassInfo fci = fastClassInfo;
-            return fci.f2.invoke(fci.i2, obj, args);
-        } catch (InvocationTargetException e) {
-            throw e.getTargetException();
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/Mixin.java b/cglib-and-asm/src/org/mockito/cglib/proxy/Mixin.java
deleted file mode 100644
index b189ba7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/Mixin.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.*;
-
-
-
-/**
- * <code>Mixin</code> allows
- * multiple objects to be combined into a single larger object. The
- * methods in the generated object simply call the original methods in the
- * underlying "delegate" objects.
- * @author Chris Nokleberg
- * @version $Id: Mixin.java,v 1.7 2005/09/27 11:42:27 baliuka Exp $
- */
-abstract public class Mixin {
-    private static final MixinKey KEY_FACTORY =
-      (MixinKey)KeyFactory.create(MixinKey.class, KeyFactory.CLASS_BY_NAME);
-    private static final Map ROUTE_CACHE = Collections.synchronizedMap(new HashMap());
-
-    public static final int STYLE_INTERFACES = 0;
-    public static final int STYLE_BEANS = 1;
-    public static final int STYLE_EVERYTHING = 2;
-
-    interface MixinKey {
-        public Object newInstance(int style, String[] classes, int[] route);
-    }
-
-    abstract public Mixin newInstance(Object[] delegates);
-
-    /**
-     * Helper method to create an interface mixin. For finer control over the
-     * generated instance, use a new instance of <code>Mixin</code>
-     * instead of this static method.
-     * TODO
-     */
-    public static Mixin create(Object[] delegates) {
-        Generator gen = new Generator();
-        gen.setDelegates(delegates);
-        return gen.create();
-    }
-
-    /**
-     * Helper method to create an interface mixin. For finer control over the
-     * generated instance, use a new instance of <code>Mixin</code>
-     * instead of this static method.
-     * TODO
-     */
-    public static Mixin create(Class[] interfaces, Object[] delegates) {
-        Generator gen = new Generator();
-        gen.setClasses(interfaces);
-        gen.setDelegates(delegates);
-        return gen.create();
-    }
-
-    
-    public static Mixin createBean(Object[] beans) {
-    
-        return createBean(null, beans);
-    
-    }
-    /**
-     * Helper method to create a bean mixin. For finer control over the
-     * generated instance, use a new instance of <code>Mixin</code>
-     * instead of this static method.
-     * TODO
-     */
-    public static Mixin createBean(ClassLoader loader,Object[] beans) {
-        Generator gen = new Generator();
-        gen.setStyle(STYLE_BEANS);
-        gen.setDelegates(beans);
-        gen.setClassLoader(loader);
-        return gen.create();
-    }
-    
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(Mixin.class.getName());
-
-        private Class[] classes;
-        private Object[] delegates;
-        private int style = STYLE_INTERFACES;
-        
-        private int[] route;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return classes[0].getClassLoader(); // is this right?
-        }
-
-        public void setStyle(int style) {
-            switch (style) {
-            case STYLE_INTERFACES:
-            case STYLE_BEANS:
-            case STYLE_EVERYTHING:
-                this.style = style;
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown mixin style: " + style);
-            }
-        }
-
-        public void setClasses(Class[] classes) {
-            this.classes = classes;
-        }
-
-        public void setDelegates(Object[] delegates) {
-            this.delegates = delegates;
-        }
-
-        public Mixin create() {
-            if (classes == null && delegates == null) {
-                throw new IllegalStateException("Either classes or delegates must be set");
-            }
-            switch (style) {
-            case STYLE_INTERFACES:
-                if (classes == null) {
-                    Route r = route(delegates);
-                    classes = r.classes;
-                    route = r.route;
-                }
-                break;
-            case STYLE_BEANS:
-                // fall-through
-            case STYLE_EVERYTHING:
-                if (classes == null) {
-                    classes = ReflectUtils.getClasses(delegates);
-                } else {
-                    if (delegates != null) {
-                        Class[] temp = ReflectUtils.getClasses(delegates);
-                        if (classes.length != temp.length) {
-                            throw new IllegalStateException("Specified classes are incompatible with delegates");
-                        }
-                        for (int i = 0; i < classes.length; i++) {
-                            if (!classes[i].isAssignableFrom(temp[i])) {
-                                throw new IllegalStateException("Specified class " + classes[i] + " is incompatible with delegate class " + temp[i] + " (index " + i + ")");
-                            }
-                        }
-                    }
-                }
-            }
-            setNamePrefix(classes[ReflectUtils.findPackageProtected(classes)].getName());
-            
-            return (Mixin)super.create(KEY_FACTORY.newInstance(style, ReflectUtils.getNames( classes ), route));
-        }
-
-        public void generateClass(ClassVisitor v) {
-            switch (style) {
-            case STYLE_INTERFACES:
-                new MixinEmitter(v, getClassName(), classes, route);
-                break;
-            case STYLE_BEANS:
-                new MixinBeanEmitter(v, getClassName(), classes);
-                break;
-            case STYLE_EVERYTHING:
-                new MixinEverythingEmitter(v, getClassName(), classes);
-                break;
-            }
-        }
-
-        protected Object firstInstance(Class type) {
-            return ((Mixin)ReflectUtils.newInstance(type)).newInstance(delegates);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return ((Mixin)instance).newInstance(delegates);
-        }
-    }
-
-    public static Class[] getClasses(Object[] delegates) {
-        return (Class[])route(delegates).classes.clone();
-    }
-
-//     public static int[] getRoute(Object[] delegates) {
-//         return (int[])route(delegates).route.clone();
-//     }
-        
-    private static Route route(Object[] delegates) {
-        Object key = ClassesKey.create(delegates);
-        Route route = (Route)ROUTE_CACHE.get(key);
-        if (route == null) {
-            ROUTE_CACHE.put(key, route = new Route(delegates));
-        }
-        return route;
-    }
-
-    private static class Route
-    {
-        private Class[] classes;
-        private int[] route;
-
-        Route(Object[] delegates) {
-            Map map = new HashMap();
-            ArrayList collect = new ArrayList();
-            for (int i = 0; i < delegates.length; i++) {
-                Class delegate = delegates[i].getClass();
-                collect.clear();
-                ReflectUtils.addAllInterfaces(delegate, collect);
-                for (Iterator it = collect.iterator(); it.hasNext();) {
-                    Class iface = (Class)it.next();
-                    if (!map.containsKey(iface)) {
-                        map.put(iface, new Integer(i));
-                    }
-                }
-            }
-            classes = new Class[map.size()];
-            route = new int[map.size()];
-            int index = 0;
-            for (Iterator it = map.keySet().iterator(); it.hasNext();) {
-                Class key = (Class)it.next();
-                classes[index] = key;
-                route[index] = ((Integer)map.get(key)).intValue();
-                index++;
-            }
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/MixinBeanEmitter.java b/cglib-and-asm/src/org/mockito/cglib/proxy/MixinBeanEmitter.java
deleted file mode 100644
index 9b47798..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/MixinBeanEmitter.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.ReflectUtils;
-
-/**
- * @author Chris Nokleberg
- * @version $Id: MixinBeanEmitter.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $
- */
-class MixinBeanEmitter extends MixinEmitter {
-    public MixinBeanEmitter(ClassVisitor v, String className, Class[] classes) {
-        super(v, className, classes, null);
-    }
-
-    protected Class[] getInterfaces(Class[] classes) {
-        return null;
-    }
-
-    protected Method[] getMethods(Class type) {
-        return ReflectUtils.getPropertyMethods(ReflectUtils.getBeanProperties(type), true, true);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/MixinEmitter.java b/cglib-and-asm/src/org/mockito/cglib/proxy/MixinEmitter.java
deleted file mode 100644
index f4460b4..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/MixinEmitter.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * @author Chris Nokleberg
- * @version $Id: MixinEmitter.java,v 1.9 2006/08/27 21:04:37 herbyderby Exp $
- */
-class MixinEmitter extends ClassEmitter {
-    private static final String FIELD_NAME = "CGLIB$DELEGATES";
-    private static final Signature CSTRUCT_OBJECT_ARRAY =
-      TypeUtils.parseConstructor("Object[]");
-    private static final Type MIXIN =
-      TypeUtils.parseType("org.mockito.cglib.proxy.Mixin");
-    private static final Signature NEW_INSTANCE =
-      new Signature("newInstance", MIXIN, new Type[]{ Constants.TYPE_OBJECT_ARRAY });
-
-    public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) {
-        super(v);
-
-        begin_class(Constants.V1_2,
-                    Constants.ACC_PUBLIC,
-                    className,
-                    MIXIN,
-                    TypeUtils.getTypes(getInterfaces(classes)),
-                    Constants.SOURCE_FILE);
-        EmitUtils.null_constructor(this);
-        EmitUtils.factory_method(this, NEW_INSTANCE);
-
-        declare_field(Constants.ACC_PRIVATE, FIELD_NAME, Constants.TYPE_OBJECT_ARRAY, null);
-
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null);
-        e.load_this();
-        e.super_invoke_constructor();
-        e.load_this();
-        e.load_arg(0);
-        e.putfield(FIELD_NAME);
-        e.return_value();
-        e.end_method();
-
-        Set unique = new HashSet();
-        for (int i = 0; i < classes.length; i++) {
-            Method[] methods = getMethods(classes[i]);
-            for (int j = 0; j < methods.length; j++) {
-                if (unique.add(MethodWrapper.create(methods[j]))) {
-                    MethodInfo method = ReflectUtils.getMethodInfo(methods[j]);
-                    e = EmitUtils.begin_method(this, method, Constants.ACC_PUBLIC);
-                    e.load_this();
-                    e.getfield(FIELD_NAME);
-                    e.aaload((route != null) ? route[i] : i);
-                    e.checkcast(method.getClassInfo().getType());
-                    e.load_args();
-                    e.invoke(method);
-                    e.return_value();
-                    e.end_method();
-                }
-            }
-        }
-
-        end_class();
-    }
-
-    protected Class[] getInterfaces(Class[] classes) {
-        return classes;
-    }
-
-    protected Method[] getMethods(Class type) {
-        return type.getMethods();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/MixinEverythingEmitter.java b/cglib-and-asm/src/org/mockito/cglib/proxy/MixinEverythingEmitter.java
deleted file mode 100644
index 2586032..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/MixinEverythingEmitter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.CollectionUtils;
-import org.mockito.cglib.core.ReflectUtils;
-import org.mockito.cglib.core.RejectModifierPredicate;
-
-/**
- * @author Chris Nokleberg
- * @version $Id: MixinEverythingEmitter.java,v 1.3 2004/06/24 21:15:19 herbyderby Exp $
- */
-class MixinEverythingEmitter extends MixinEmitter {
-
-    public MixinEverythingEmitter(ClassVisitor v, String className, Class[] classes) {
-        super(v, className, classes, null);
-    }
-
-    protected Class[] getInterfaces(Class[] classes) {
-        List list = new ArrayList();
-        for (int i = 0; i < classes.length; i++) {
-            ReflectUtils.addAllInterfaces(classes[i], list);
-        }
-        return (Class[])list.toArray(new Class[list.size()]);
-    }
-
-    protected Method[] getMethods(Class type) {
-        List methods = new ArrayList(Arrays.asList(type.getMethods()));
-        CollectionUtils.filter(methods, new RejectModifierPredicate(Modifier.FINAL | Modifier.STATIC));
-        return (Method[])methods.toArray(new Method[methods.size()]);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/NoOp.java b/cglib-and-asm/src/org/mockito/cglib/proxy/NoOp.java
deleted file mode 100644
index 727573f..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/NoOp.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * Methods using this {@link Enhancer} callback will delegate directly to the
- * default (super) implementation in the base class.
- */
-public interface NoOp extends Callback
-{
-    /**
-     * A thread-safe singleton instance of the <code>NoOp</code> callback.
-     */
-    public static final NoOp INSTANCE = new NoOp() { };
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/NoOpGenerator.java b/cglib-and-asm/src/org/mockito/cglib/proxy/NoOpGenerator.java
deleted file mode 100644
index 16701a7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/NoOpGenerator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.mockito.cglib.core.*;
-
-class NoOpGenerator
-implements CallbackGenerator
-{
-    public static final NoOpGenerator INSTANCE = new NoOpGenerator();
-
-    public void generate(ClassEmitter ce, Context context, List methods) {
-        for (Iterator it = methods.iterator(); it.hasNext();) {
-            MethodInfo method = (MethodInfo)it.next();
-            if (TypeUtils.isProtected(context.getOriginalModifiers(method)) &&
-                TypeUtils.isPublic(method.getModifiers())) {
-                CodeEmitter e = EmitUtils.begin_method(ce, method);
-                e.load_this();
-                e.load_args();
-                e.super_invoke();
-                e.return_value();
-                e.end_method();
-            }
-        }
-    }
-    
-    public void generateStatic(CodeEmitter e, Context context, List methods) { }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/Proxy.java b/cglib-and-asm/src/org/mockito/cglib/proxy/Proxy.java
deleted file mode 100644
index 80387e0..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/Proxy.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.List;
-
-import org.mockito.cglib.core.CodeGenerationException;
-
-/**
- * This class is meant to be used as replacement for
- * <code>java.lang.reflect.Proxy</code> under JDK 1.2. There are some known
- * subtle differences:
- * <ul>
- * <li>The exceptions returned by invoking <code>getExceptionTypes</code>
- * on the <code>Method</code> passed to the <code>invoke</code> method
- * <b>are</b> the exact set that can be thrown without resulting in an
- * <code>UndeclaredThrowableException</code> being thrown.
- * <li>{@link UndeclaredThrowableException} is used instead
- * of <code>java.lang.reflect.UndeclaredThrowableException</code>.
- * </ul>
- * <p>
- * @version $Id: Proxy.java,v 1.6 2004/06/24 21:15:19 herbyderby Exp $
- */
-public class Proxy implements Serializable {
-    protected InvocationHandler h;
-
-    private static final CallbackFilter BAD_OBJECT_METHOD_FILTER = new CallbackFilter() {
-        public int accept(Method method, List<Method> allMethods) {
-            if (method.getDeclaringClass().getName().equals("java.lang.Object")) {
-                String name = method.getName();
-                if (!(name.equals("hashCode") ||
-                      name.equals("equals") ||
-                      name.equals("toString"))) {
-                    return 1;
-                }
-            }
-            return 0;
-        }
-    };
-
-    protected Proxy(InvocationHandler h) {
-        Enhancer.registerCallbacks(getClass(), new Callback[]{ h, null });
-        this.h = h;
-    }
-
-    // private for security of isProxyClass
-    private static class ProxyImpl extends Proxy {
-        protected ProxyImpl(InvocationHandler h) {
-            super(h);
-        }
-    }
-
-    public static InvocationHandler getInvocationHandler(Object proxy) {
-        if (!(proxy instanceof ProxyImpl)) {
-            throw new IllegalArgumentException("Object is not a proxy");
-        }
-        return ((Proxy)proxy).h;
-    }
-
-    public static Class getProxyClass(ClassLoader loader, Class[] interfaces) {
-        Enhancer e = new Enhancer();
-        e.setSuperclass(ProxyImpl.class);
-        e.setInterfaces(interfaces);
-        e.setCallbackTypes(new Class[]{
-            InvocationHandler.class,
-            NoOp.class,
-        });
-        e.setCallbackFilter(BAD_OBJECT_METHOD_FILTER);
-        e.setUseFactory(false);
-        return e.createClass();
-    }
-
-    public static boolean isProxyClass(Class cl) {
-        return cl.getSuperclass().equals(ProxyImpl.class);
-    }
-
-    public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) {
-        try {
-            Class clazz = getProxyClass(loader, interfaces);
-            return clazz.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(new Object[]{ h });
-        } catch (RuntimeException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/ProxyRefDispatcher.java b/cglib-and-asm/src/org/mockito/cglib/proxy/ProxyRefDispatcher.java
deleted file mode 100644
index 4f30018..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/ProxyRefDispatcher.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.proxy;
-
-/**
- * Dispatching {@link Enhancer} callback. This is the same as the
- * {@link Dispatcher} except for the addition of an argument
- * which references the proxy object.
- */
-public interface ProxyRefDispatcher extends Callback {
-    /**
-     * Return the object which the original method invocation should
-     * be dispatched. This method is called for <b>every</b> method invocation.
-     * @param proxy a reference to the proxy (generated) object
-     * @return an object that can invoke the method
-     */
-    Object loadObject(Object proxy) throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/proxy/UndeclaredThrowableException.java b/cglib-and-asm/src/org/mockito/cglib/proxy/UndeclaredThrowableException.java
deleted file mode 100644
index 98b7ad7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/proxy/UndeclaredThrowableException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2002,2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.mockito.cglib.proxy;
-
-import org.mockito.cglib.core.CodeGenerationException;
-
-/**
- * Used by {@link Proxy} as a replacement for <code>java.lang.reflect.UndeclaredThrowableException</code>.
- * @author Juozas Baliuka
- */
-public class UndeclaredThrowableException extends CodeGenerationException {
-    /**
-     * Creates a new instance of <code>UndeclaredThrowableException</code> without detail message.
-     */
-    public UndeclaredThrowableException(Throwable t) {
-        super(t);
-    }
-    
-    public Throwable getUndeclaredThrowable() {
-        return getCause();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/ConstructorDelegate.java b/cglib-and-asm/src/org/mockito/cglib/reflect/ConstructorDelegate.java
deleted file mode 100644
index d6fe3b7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/ConstructorDelegate.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * @author Chris Nokleberg
- * @version $Id: ConstructorDelegate.java,v 1.20 2006/03/05 02:43:19 herbyderby Exp $
- */
-abstract public class ConstructorDelegate {
-    private static final ConstructorKey KEY_FACTORY =
-      (ConstructorKey)KeyFactory.create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME);
-    
-    interface ConstructorKey {
-        public Object newInstance(String declaring, String iface);
-    }
-
-    protected ConstructorDelegate() {
-    }
-
-    public static ConstructorDelegate create(Class targetClass, Class iface) {
-        Generator gen = new Generator();
-        gen.setTargetClass(targetClass);
-        gen.setInterface(iface);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(ConstructorDelegate.class.getName());
-        private static final Type CONSTRUCTOR_DELEGATE =
-          TypeUtils.parseType("org.mockito.cglib.reflect.ConstructorDelegate");
-
-        private Class iface;
-        private Class targetClass;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        public void setInterface(Class iface) {
-            this.iface = iface;
-        }
-
-        public void setTargetClass(Class targetClass) {
-            this.targetClass = targetClass;
-        }
-
-        public ConstructorDelegate create() {
-            setNamePrefix(targetClass.getName());
-            Object key = KEY_FACTORY.newInstance(iface.getName(), targetClass.getName());
-            return (ConstructorDelegate)super.create(key);
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return targetClass.getClassLoader();
-        }
-
-        public void generateClass(ClassVisitor v) {
-            setNamePrefix(targetClass.getName());
-
-            final Method newInstance = ReflectUtils.findNewInstance(iface);
-            if (!newInstance.getReturnType().isAssignableFrom(targetClass)) {
-                throw new IllegalArgumentException("incompatible return type");
-            }
-            final Constructor constructor;
-            try {
-                constructor = targetClass.getDeclaredConstructor(newInstance.getParameterTypes());
-            } catch (NoSuchMethodException e) {
-                throw new IllegalArgumentException("interface does not match any known constructor");
-            }
-
-            ClassEmitter ce = new ClassEmitter(v);
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           CONSTRUCTOR_DELEGATE,
-                           new Type[]{ Type.getType(iface) },
-                           Constants.SOURCE_FILE);
-            Type declaring = Type.getType(constructor.getDeclaringClass());
-            EmitUtils.null_constructor(ce);
-            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
-                                            ReflectUtils.getSignature(newInstance),
-                                            ReflectUtils.getExceptionTypes(newInstance));
-            e.new_instance(declaring);
-            e.dup();
-            e.load_args();
-            e.invoke_constructor(declaring, ReflectUtils.getSignature(constructor));
-            e.return_value();
-            e.end_method();
-            ce.end_class();
-        }
-
-        protected Object firstInstance(Class type) {
-            return ReflectUtils.newInstance(type);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return instance;
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/FastClass.java b/cglib-and-asm/src/org/mockito/cglib/reflect/FastClass.java
deleted file mode 100644
index 3a6d241..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/FastClass.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-abstract public class FastClass
-{
-    private Class type;
-
-    protected FastClass() {
-        throw new Error("Using the FastClass empty constructor--please report to the cglib-devel mailing list");
-    }
-
-    protected FastClass(Class type) {
-        this.type = type;
-    }
-
-    public static FastClass create(Class type) {
-    
-        return create(type.getClassLoader(),type);
-        
-    }
-    public static FastClass create(ClassLoader loader, Class type) {
-        Generator gen = new Generator();
-        gen.setType(type);
-        gen.setClassLoader(loader);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator
-    {
-        private static final Source SOURCE = new Source(FastClass.class.getName());
-        private Class type;
-        
-        public Generator() {
-            super(SOURCE);
-        }
-
-        public void setType(Class type) {
-            this.type = type;
-        }
-        
-        public FastClass create() {
-            setNamePrefix(type.getName());
-            return (FastClass)super.create(type.getName());
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return type.getClassLoader();
-        }
-
-        public void generateClass(ClassVisitor v) throws Exception {
-            new FastClassEmitter(v, getClassName(), type);
-        }
-
-        protected Object firstInstance(Class type) {
-            return ReflectUtils.newInstance(type,
-                                            new Class[]{ Class.class },
-                                            new Object[]{ this.type });
-        }
-
-        protected Object nextInstance(Object instance) {
-            return instance;
-        }
-    }
-    
-    public Object invoke(String name, Class[] parameterTypes, Object obj, Object[] args) throws InvocationTargetException {
-        return invoke(getIndex(name, parameterTypes), obj, args);
-    }
-
-    public Object newInstance() throws InvocationTargetException {
-        return newInstance(getIndex(Constants.EMPTY_CLASS_ARRAY), null);
-    }
-
-    public Object newInstance(Class[] parameterTypes, Object[] args) throws InvocationTargetException {
-        return newInstance(getIndex(parameterTypes), args);
-    }
-    
-    public FastMethod getMethod(Method method) {
-        return new FastMethod(this, method);
-    }
-
-    public FastConstructor getConstructor(Constructor constructor) {
-        return new FastConstructor(this, constructor);
-    }
-
-    public FastMethod getMethod(String name, Class[] parameterTypes) {
-        try {
-            return getMethod(type.getMethod(name, parameterTypes));
-        } catch (NoSuchMethodException e) {
-            throw new NoSuchMethodError(e.getMessage());
-        }
-    }
-
-    public FastConstructor getConstructor(Class[] parameterTypes) {
-        try {
-            return getConstructor(type.getConstructor(parameterTypes));
-        } catch (NoSuchMethodException e) {
-            throw new NoSuchMethodError(e.getMessage());
-        }
-    }
-
-    public String getName() {
-        return type.getName();
-    }
-
-    public Class getJavaClass() {
-        return type;
-    }
-
-    public String toString() {
-        return type.toString();
-    }
-
-    public int hashCode() {
-        return type.hashCode();
-    }
-
-    public boolean equals(Object o) {
-        if (o == null || !(o instanceof FastClass)) {
-            return false;
-        }
-        return type.equals(((FastClass)o).type);
-    }
-
-    /**
-     * Return the index of the matching method. The index may be used
-     * later to invoke the method with less overhead. If more than one
-     * method matches (i.e. they differ by return type only), one is
-     * chosen arbitrarily.
-     * @see #invoke(int, Object, Object[])
-     * @param name the method name
-     * @param parameterTypes the parameter array
-     * @return the index, or <code>-1</code> if none is found.
-     */
-    abstract public int getIndex(String name, Class[] parameterTypes);
-
-    /**
-     * Return the index of the matching constructor. The index may be used
-     * later to create a new instance with less overhead.
-     * @see #newInstance(int, Object[])
-     * @param parameterTypes the parameter array
-     * @return the constructor index, or <code>-1</code> if none is found.
-     */
-    abstract public int getIndex(Class[] parameterTypes);
-
-    /**
-     * Invoke the method with the specified index.
-     * @see getIndex(name, Class[])
-     * @param index the method index
-     * @param obj the object the underlying method is invoked from
-     * @param args the arguments used for the method call
-     * @throws java.lang.reflect.InvocationTargetException if the underlying method throws an exception
-     */
-    abstract public Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException;
-
-    /**
-     * Create a new instance using the specified constructor index and arguments.
-     * @see getIndex(Class[])
-     * @param index the constructor index
-     * @param args the arguments passed to the constructor
-     * @throws java.lang.reflect.InvocationTargetException if the constructor throws an exception
-     */
-    abstract public Object newInstance(int index, Object[] args) throws InvocationTargetException;
-
-    abstract public int getIndex(Signature sig);
-
-    /**
-     * Returns the maximum method index for this class.
-     */
-    abstract public int getMaxIndex();
-
-    protected static String getSignatureWithoutReturnType(String name, Class[] parameterTypes) {
-        StringBuffer sb = new StringBuffer();
-        sb.append(name);
-        sb.append('(');
-        for (int i = 0; i < parameterTypes.length; i++) {
-            sb.append(Type.getDescriptor(parameterTypes[i]));
-        }
-        sb.append(')');
-        return sb.toString();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/FastClassEmitter.java b/cglib-and-asm/src/org/mockito/cglib/reflect/FastClassEmitter.java
deleted file mode 100644
index eb4f783..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/FastClassEmitter.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-    
-class FastClassEmitter extends ClassEmitter {
-    private static final Signature CSTRUCT_CLASS =
-      TypeUtils.parseConstructor("Class");
-    private static final Signature METHOD_GET_INDEX =
-      TypeUtils.parseSignature("int getIndex(String, Class[])");
-    private static final Signature SIGNATURE_GET_INDEX =
-      new Signature("getIndex", Type.INT_TYPE, new Type[]{ Constants.TYPE_SIGNATURE });
-    private static final Signature TO_STRING =
-      TypeUtils.parseSignature("String toString()");
-    private static final Signature CONSTRUCTOR_GET_INDEX =
-      TypeUtils.parseSignature("int getIndex(Class[])");
-    private static final Signature INVOKE =
-      TypeUtils.parseSignature("Object invoke(int, Object, Object[])");
-    private static final Signature NEW_INSTANCE =
-      TypeUtils.parseSignature("Object newInstance(int, Object[])");
-    private static final Signature GET_MAX_INDEX =
-      TypeUtils.parseSignature("int getMaxIndex()");
-    private static final Signature GET_SIGNATURE_WITHOUT_RETURN_TYPE =
-      TypeUtils.parseSignature("String getSignatureWithoutReturnType(String, Class[])");
-    private static final Type FAST_CLASS =
-      TypeUtils.parseType("org.mockito.cglib.reflect.FastClass");
-    private static final Type ILLEGAL_ARGUMENT_EXCEPTION =
-      TypeUtils.parseType("IllegalArgumentException");
-    private static final Type INVOCATION_TARGET_EXCEPTION =
-      TypeUtils.parseType("java.lang.reflect.InvocationTargetException");
-    private static final Type[] INVOCATION_TARGET_EXCEPTION_ARRAY = { INVOCATION_TARGET_EXCEPTION };
-    
-    public FastClassEmitter(ClassVisitor v, String className, Class type) {
-        super(v);
-
-        Type base = Type.getType(type);
-        begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE);
-
-        // constructor
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_CLASS, null);
-        e.load_this();
-        e.load_args();
-        e.super_invoke_constructor(CSTRUCT_CLASS);
-        e.return_value();
-        e.end_method();
-
-        VisibilityPredicate vp = new VisibilityPredicate(type, false);
-        List methods = ReflectUtils.addAllMethods(type, new ArrayList());
-        CollectionUtils.filter(methods, vp);
-        CollectionUtils.filter(methods, new DuplicatesPredicate());
-        List constructors = new ArrayList(Arrays.asList(type.getDeclaredConstructors()));
-        CollectionUtils.filter(constructors, vp);
-        
-        // getIndex(String)
-        emitIndexBySignature(methods);
-
-        // getIndex(String, Class[])
-        emitIndexByClassArray(methods);
-        
-        // getIndex(Class[])
-        e = begin_method(Constants.ACC_PUBLIC, CONSTRUCTOR_GET_INDEX, null);
-        e.load_args();
-        List info = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
-        EmitUtils.constructor_switch(e, info, new GetIndexCallback(e, info));
-        e.end_method();
-
-        // invoke(int, Object, Object[])
-        e = begin_method(Constants.ACC_PUBLIC, INVOKE, INVOCATION_TARGET_EXCEPTION_ARRAY);
-        e.load_arg(1);
-        e.checkcast(base);
-        e.load_arg(0);
-        invokeSwitchHelper(e, methods, 2, base);
-        e.end_method();
-
-        // newInstance(int, Object[])
-        e = begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, INVOCATION_TARGET_EXCEPTION_ARRAY);
-        e.new_instance(base);
-        e.dup();
-        e.load_arg(0);
-        invokeSwitchHelper(e, constructors, 1, base);
-        e.end_method();
-
-        // getMaxIndex()
-        e = begin_method(Constants.ACC_PUBLIC, GET_MAX_INDEX, null);
-        e.push(methods.size() - 1);
-        e.return_value();
-        e.end_method();
-
-        end_class();
-    }
-
-    // TODO: support constructor indices ("<init>")
-    private void emitIndexBySignature(List methods) {
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SIGNATURE_GET_INDEX, null);
-        List signatures = CollectionUtils.transform(methods, new Transformer() {
-            public Object transform(Object obj) {
-                return ReflectUtils.getSignature((Method)obj).toString();
-            }
-        });
-        e.load_arg(0);
-        e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
-        signatureSwitchHelper(e, signatures);
-        e.end_method();
-    }
-
-    private static final int TOO_MANY_METHODS = 100; // TODO
-    private void emitIndexByClassArray(List methods) {
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, METHOD_GET_INDEX, null);
-        if (methods.size() > TOO_MANY_METHODS) {
-            // hack for big classes
-            List signatures = CollectionUtils.transform(methods, new Transformer() {
-                public Object transform(Object obj) {
-                    String s = ReflectUtils.getSignature((Method)obj).toString();
-                    return s.substring(0, s.lastIndexOf(')') + 1);
-                }
-            });
-            e.load_args();
-            e.invoke_static(FAST_CLASS, GET_SIGNATURE_WITHOUT_RETURN_TYPE);
-            signatureSwitchHelper(e, signatures);
-        } else {
-            e.load_args();
-            List info = CollectionUtils.transform(methods, MethodInfoTransformer.getInstance());
-            EmitUtils.method_switch(e, info, new GetIndexCallback(e, info));
-        }
-        e.end_method();
-    }
-
-    private void signatureSwitchHelper(final CodeEmitter e, final List signatures) {
-        ObjectSwitchCallback callback = new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                // TODO: remove linear indexOf
-                e.push(signatures.indexOf(key));
-                e.return_value();
-            }
-            public void processDefault() {
-                e.push(-1);
-                e.return_value();
-            }
-        };
-        EmitUtils.string_switch(e,
-                                (String[])signatures.toArray(new String[signatures.size()]),
-                                Constants.SWITCH_STYLE_HASH,
-                                callback);
-    }
-
-    private static void invokeSwitchHelper(final CodeEmitter e, List members, final int arg, final Type base) {
-        final List info = CollectionUtils.transform(members, MethodInfoTransformer.getInstance());        
-        final Label illegalArg = e.make_label();
-        Block block = e.begin_block();
-        e.process_switch(getIntRange(info.size()), new ProcessSwitchCallback() {
-            public void processCase(int key, Label end) {
-                MethodInfo method = (MethodInfo)info.get(key);
-                Type[] types = method.getSignature().getArgumentTypes();
-                for (int i = 0; i < types.length; i++) {
-                    e.load_arg(arg);
-                    e.aaload(i);
-                    e.unbox(types[i]);
-                }
-                // TODO: change method lookup process so MethodInfo will already reference base
-                // instead of superclass when superclass method is inaccessible
-                e.invoke(method, base);
-                if (!TypeUtils.isConstructor(method)) {
-                    e.box(method.getSignature().getReturnType());
-                }
-                e.return_value();
-            }
-            public void processDefault() {
-                e.goTo(illegalArg);
-            }
-        });
-        block.end();
-        EmitUtils.wrap_throwable(block, INVOCATION_TARGET_EXCEPTION);
-        e.mark(illegalArg);
-        e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Cannot find matching method/constructor");
-    }
-
-    private static class GetIndexCallback implements ObjectSwitchCallback {
-        private CodeEmitter e;
-        private Map indexes = new HashMap();
-
-        public GetIndexCallback(CodeEmitter e, List methods) {
-            this.e = e;
-            int index = 0;
-            for (Iterator it = methods.iterator(); it.hasNext();) {
-                indexes.put(it.next(), new Integer(index++));
-            }
-        }
-            
-        public void processCase(Object key, Label end) {
-            e.push(((Integer)indexes.get(key)).intValue());
-            e.return_value();
-        }
-        
-        public void processDefault() {
-            e.push(-1);
-            e.return_value();
-        }
-    }
-    
-    private static int[] getIntRange(int length) {
-        int[] range = new int[length];
-        for (int i = 0; i < length; i++) {
-            range[i] = i;
-        }
-        return range;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/FastConstructor.java b/cglib-and-asm/src/org/mockito/cglib/reflect/FastConstructor.java
deleted file mode 100644
index 292dde2..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/FastConstructor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-public class FastConstructor extends FastMember
-{
-    FastConstructor(FastClass fc, Constructor constructor) {
-        super(fc, constructor, fc.getIndex(constructor.getParameterTypes()));
-    }
-
-    public Class[] getParameterTypes() {
-        return ((Constructor)member).getParameterTypes();
-    }
-
-    public Class[] getExceptionTypes() {
-        return ((Constructor)member).getExceptionTypes();
-    }
-
-    public Object newInstance() throws InvocationTargetException {
-        return fc.newInstance(index, null);
-    }
-
-    public Object newInstance(Object[] args) throws InvocationTargetException {
-        return fc.newInstance(index, args);
-    }
-
-    public Constructor getJavaConstructor() {
-        return (Constructor)member;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/FastMember.java b/cglib-and-asm/src/org/mockito/cglib/reflect/FastMember.java
deleted file mode 100644
index da644d3..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/FastMember.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.Member;
-
-abstract public class FastMember
-{
-    protected FastClass fc;
-    protected Member member;
-    protected int index;
-
-    protected FastMember(FastClass fc, Member member, int index) {
-        this.fc = fc;
-        this.member = member;
-        this.index = index;
-    }
-
-    abstract public Class[] getParameterTypes();
-    abstract public Class[] getExceptionTypes();
-
-    public int getIndex() {
-        return index;
-    }
-
-    public String getName() {
-        return member.getName();
-    }
-
-    public Class getDeclaringClass() {
-        return fc.getJavaClass();
-    }
-
-    public int getModifiers() {
-        return member.getModifiers();
-    }
-
-    public String toString() {
-        return member.toString();
-    }
-
-    public int hashCode() {
-        return member.hashCode();
-    }
-
-    public boolean equals(Object o) {
-        if (o == null || !(o instanceof FastMember)) {
-            return false;
-        }
-        return member.equals(((FastMember)o).member);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/FastMethod.java b/cglib-and-asm/src/org/mockito/cglib/reflect/FastMethod.java
deleted file mode 100644
index 1665c47..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/FastMethod.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-public class FastMethod extends FastMember
-{
-    FastMethod(FastClass fc, Method method) {
-        super(fc, method, helper(fc, method));
-    }
-
-    private static int helper(FastClass fc, Method method) {
-        int index = fc.getIndex(method.getName(), method.getParameterTypes());
-        if (index < 0) {
-            Class[] types = method.getParameterTypes();
-            System.err.println("hash=" + method.getName().hashCode() + " size=" + types.length);
-            for (int i = 0; i < types.length; i++) {
-                System.err.println("  types[" + i + "]=" + types[i].getName());
-            }
-            throw new IllegalArgumentException("Cannot find method " + method);
-        }
-        return index;
-    }
-
-    public Class getReturnType() {
-        return ((Method)member).getReturnType();
-    }
-
-    public Class[] getParameterTypes() {
-        return ((Method)member).getParameterTypes();
-    }
-
-    public Class[] getExceptionTypes() {
-        return ((Method)member).getExceptionTypes();
-    }
-
-    public Object invoke(Object obj, Object[] args) throws InvocationTargetException {
-        return fc.invoke(index, obj, args);
-    }
-
-    public Method getJavaMethod() {
-        return (Method)member;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/MethodDelegate.java b/cglib-and-asm/src/org/mockito/cglib/reflect/MethodDelegate.java
deleted file mode 100644
index fb211e7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/MethodDelegate.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.*;
-import org.mockito.cglib.core.*;
-
-// TODO: don't require exact match for return type
-
-/**
- * <b>DOCUMENTATION FROM APACHE AVALON DELEGATE CLASS</b>
- *
- * <p>
- * Delegates are a typesafe pointer to another method.  Since Java does not
- * have language support for such a construct, this utility will construct
- * a proxy that forwards method calls to any method with the same signature.
- * This utility is inspired in part by the C# delegate mechanism.  We
- * implemented it in a Java-centric manner.
- * </p>
- *
- * <h2>Delegate</h2>
- * <p>
- *   Any interface with one method can become the interface for a delegate.
- *   Consider the example below:
- * </p>
- *
- * <pre>
- *   public interface MainDelegate {
- *       int main(String[] args);
- *   }
- * </pre>
- *
- * <p>
- *   The interface above is an example of an interface that can become a
- *   delegate.  It has only one method, and the interface is public.  In
- *   order to create a delegate for that method, all we have to do is
- *   call <code>MethodDelegate.create(this, "alternateMain", MainDelegate.class)</code>.
- *   The following program will show how to use it:
- * </p>
- *
- * <pre>
- *   public class Main {
- *       public static int main( String[] args ) {
- *           Main newMain = new Main();
- *           MainDelegate start = (MainDelegate)
- *               MethodDelegate.create(newMain, "alternateMain", MainDelegate.class);
- *           return start.main( args );
- *       }
- *
- *       public int alternateMain( String[] args ) {
- *           for (int i = 0; i < args.length; i++) {
- *               System.out.println( args[i] );
- *           }
- *           return args.length;
- *       }
- *   }
- * </pre>
- *
- * <p>
- *   By themselves, delegates don't do much.  Their true power lies in the fact that
- *   they can be treated like objects, and passed to other methods.  In fact that is
- *   one of the key building blocks of building Intelligent Agents which in tern are
- *   the foundation of artificial intelligence.  In the above program, we could have
- *   easily created the delegate to match the static <code>main</code> method by
- *   substituting the delegate creation call with this:
- *   <code>MethodDelegate.createStatic(getClass(), "main", MainDelegate.class)</code>.
- * </p>
- * <p>
- *   Another key use for Delegates is to register event listeners.  It is much easier
- *   to have all the code for your events separated out into methods instead of individual
- *   classes.  One of the ways Java gets around that is to create anonymous classes.
- *   They are particularly troublesome because many Debuggers do not know what to do
- *   with them.  Anonymous classes tend to duplicate alot of code as well.  We can
- *   use any interface with one declared method to forward events to any method that
- *   matches the signature (although the method name can be different).
- * </p>
- *
- * <h3>Equality</h3>
- *  The criteria that we use to test if two delegates are equal are:
- *   <ul>
- *     <li>
- *       They both refer to the same instance.  That is, the <code>instance</code>
- *       parameter passed to the newDelegate method was the same for both. The
- *       instances are compared with the identity equality operator, <code>==</code>.
- *     </li>
- *     <li>They refer to the same method as resolved by <code>Method.equals</code>.</li>
- *   </ul>
- *
- * @version $Id: MethodDelegate.java,v 1.25 2006/03/05 02:43:19 herbyderby Exp $
- */
-abstract public class MethodDelegate {
-    private static final MethodDelegateKey KEY_FACTORY =
-      (MethodDelegateKey)KeyFactory.create(MethodDelegateKey.class, KeyFactory.CLASS_BY_NAME);
-
-    protected Object target;
-    protected String eqMethod;
-
-    interface MethodDelegateKey {
-        Object newInstance(Class delegateClass, String methodName, Class iface);
-    }
-
-    public static MethodDelegate createStatic(Class targetClass, String methodName, Class iface) {
-        Generator gen = new Generator();
-        gen.setTargetClass(targetClass);
-        gen.setMethodName(methodName);
-        gen.setInterface(iface);
-        return gen.create();
-    }
-
-    public static MethodDelegate create(Object target, String methodName, Class iface) {
-        Generator gen = new Generator();
-        gen.setTarget(target);
-        gen.setMethodName(methodName);
-        gen.setInterface(iface);
-        return gen.create();
-    }
-
-    public boolean equals(Object obj) {
-        MethodDelegate other = (MethodDelegate)obj;
-        return target == other.target && eqMethod.equals(other.eqMethod);
-    }
-
-    public int hashCode() {
-        return target.hashCode() ^ eqMethod.hashCode();
-    }
-
-    public Object getTarget() {
-        return target;
-    }
-
-    abstract public MethodDelegate newInstance(Object target);
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(MethodDelegate.class.getName());
-        private static final Type METHOD_DELEGATE =
-          TypeUtils.parseType("org.mockito.cglib.reflect.MethodDelegate");
-        private static final Signature NEW_INSTANCE =
-          new Signature("newInstance", METHOD_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
-        
-        private Object target;
-        private Class targetClass;
-        private String methodName;
-        private Class iface;
-        
-        public Generator() {
-            super(SOURCE);
-        }
-
-        public void setTarget(Object target) {
-            this.target = target;
-            this.targetClass = target.getClass();
-        }
-
-        public void setTargetClass(Class targetClass) {
-            this.targetClass = targetClass;
-        }
-
-        public void setMethodName(String methodName) {
-            this.methodName = methodName;
-        }
-
-        public void setInterface(Class iface) {
-            this.iface = iface;
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return targetClass.getClassLoader();
-        }
-
-        public MethodDelegate create() {
-            setNamePrefix(targetClass.getName());
-            Object key = KEY_FACTORY.newInstance(targetClass, methodName, iface);
-            return (MethodDelegate)super.create(key);
-        }
-
-        protected Object firstInstance(Class type) {
-            return ((MethodDelegate)ReflectUtils.newInstance(type)).newInstance(target);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return ((MethodDelegate)instance).newInstance(target);
-        }
-
-        public void generateClass(ClassVisitor v) throws NoSuchMethodException {
-            Method proxy = ReflectUtils.findInterfaceMethod(iface);
-            final Method method = targetClass.getMethod(methodName, proxy.getParameterTypes());
-            if (!proxy.getReturnType().isAssignableFrom(method.getReturnType())) {
-                throw new IllegalArgumentException("incompatible return types");
-            }
-
-            MethodInfo methodInfo = ReflectUtils.getMethodInfo(method);
-
-            boolean isStatic = TypeUtils.isStatic(methodInfo.getModifiers());
-            if ((target == null) ^ isStatic) {
-                throw new IllegalArgumentException("Static method " + (isStatic ? "not " : "") + "expected");
-            }
-
-            ClassEmitter ce = new ClassEmitter(v);
-            CodeEmitter e;
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           METHOD_DELEGATE,
-                           new Type[]{ Type.getType(iface) },
-                           Constants.SOURCE_FILE);
-            ce.declare_field(Constants.PRIVATE_FINAL_STATIC, "eqMethod", Constants.TYPE_STRING, null);
-            EmitUtils.null_constructor(ce);
-
-            // generate proxied method
-            MethodInfo proxied = ReflectUtils.getMethodInfo(iface.getDeclaredMethods()[0]);
-            e = EmitUtils.begin_method(ce, proxied, Constants.ACC_PUBLIC);
-            e.load_this();
-            e.super_getfield("target", Constants.TYPE_OBJECT);
-            e.checkcast(methodInfo.getClassInfo().getType());
-            e.load_args();
-            e.invoke(methodInfo);
-            e.return_value();
-            e.end_method();
-
-            // newInstance
-            e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
-            e.new_instance_this();
-            e.dup();
-            e.dup2();
-            e.invoke_constructor_this();
-            e.getfield("eqMethod");
-            e.super_putfield("eqMethod", Constants.TYPE_STRING);
-            e.load_arg(0);
-            e.super_putfield("target", Constants.TYPE_OBJECT);
-            e.return_value();
-            e.end_method();
-
-            // static initializer
-            e = ce.begin_static();
-            e.push(methodInfo.getSignature().toString());
-            e.putfield("eqMethod");
-            e.return_value();
-            e.end_method();
-            
-            ce.end_class();
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/reflect/MulticastDelegate.java b/cglib-and-asm/src/org/mockito/cglib/reflect/MulticastDelegate.java
deleted file mode 100644
index a180a74..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/reflect/MulticastDelegate.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.reflect;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.MethodVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-abstract public class MulticastDelegate implements Cloneable {
-    protected Object[] targets = {};
-
-    protected MulticastDelegate() {
-    }
-
-    public List getTargets() {
-        return new ArrayList(Arrays.asList(targets));
-    }
-
-    abstract public MulticastDelegate add(Object target);
-
-    protected MulticastDelegate addHelper(Object target) {
-        MulticastDelegate copy = newInstance();
-        copy.targets = new Object[targets.length + 1];
-        System.arraycopy(targets, 0, copy.targets, 0, targets.length);
-        copy.targets[targets.length] = target;
-        return copy;
-    }
-
-    public MulticastDelegate remove(Object target) {
-        for (int i = targets.length - 1; i >= 0; i--) { 
-            if (targets[i].equals(target)) {
-                MulticastDelegate copy = newInstance();
-                copy.targets = new Object[targets.length - 1];
-                System.arraycopy(targets, 0, copy.targets, 0, i);
-                System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1);
-                return copy;
-            }
-        }
-        return this;
-    }
-
-    abstract public MulticastDelegate newInstance();
-
-    public static MulticastDelegate create(Class iface) {
-        Generator gen = new Generator();
-        gen.setInterface(iface);
-        return gen.create();
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(MulticastDelegate.class.getName());
-        private static final Type MULTICAST_DELEGATE =
-          TypeUtils.parseType("org.mockito.cglib.reflect.MulticastDelegate");
-        private static final Signature NEW_INSTANCE =
-          new Signature("newInstance", MULTICAST_DELEGATE, new Type[0]);
-        private static final Signature ADD_DELEGATE =
-          new Signature("add", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
-        private static final Signature ADD_HELPER =
-          new Signature("addHelper", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
-
-        private Class iface;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return iface.getClassLoader();
-        }
-
-        public void setInterface(Class iface) {
-            this.iface = iface;
-        }
-
-        public MulticastDelegate create() {
-            setNamePrefix(MulticastDelegate.class.getName());
-            return (MulticastDelegate)super.create(iface.getName());
-        }
-
-        public void generateClass(ClassVisitor cv) {
-            final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface));
-            
-            ClassEmitter ce = new ClassEmitter(cv);
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           MULTICAST_DELEGATE,
-                           new Type[]{ Type.getType(iface) },
-                           Constants.SOURCE_FILE);
-            EmitUtils.null_constructor(ce);
-
-            // generate proxied method
-            emitProxy(ce, method);
-
-            // newInstance
-            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
-            e.new_instance_this();
-            e.dup();
-            e.invoke_constructor_this();
-            e.return_value();
-            e.end_method();
-
-            // add
-            e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null);
-            e.load_this();
-            e.load_arg(0);
-            e.checkcast(Type.getType(iface));
-            e.invoke_virtual_this(ADD_HELPER);
-            e.return_value();
-            e.end_method();
-
-            ce.end_class();
-        }
-
-        private void emitProxy(ClassEmitter ce, final MethodInfo method) {
-            final CodeEmitter e = EmitUtils.begin_method(ce, method, Constants.ACC_PUBLIC);
-            Type returnType = method.getSignature().getReturnType();
-            final boolean returns = returnType != Type.VOID_TYPE;
-            Local result = null;
-            if (returns) {
-                result = e.make_local(returnType);
-                e.zero_or_null(returnType);
-                e.store_local(result);
-            }
-            e.load_this();
-            e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY);
-            final Local result2 = result;
-            EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() {
-                public void processElement(Type type) {
-                    e.checkcast(Type.getType(iface));
-                    e.load_args();
-                    e.invoke(method);
-                    if (returns) {
-                        e.store_local(result2);
-                    }
-                }
-            });
-            if (returns) {
-                e.load_local(result);
-            }
-            e.return_value();
-            e.end_method();
-        }
-
-        protected Object firstInstance(Class type) {
-            // make a new instance in case first object is used with a long list of targets
-            return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance();
-        }
-
-        protected Object nextInstance(Object instance) {
-            return ((MulticastDelegate)instance).newInstance();
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassFilterTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassFilterTransformer.java
deleted file mode 100644
index 213b8ac..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassFilterTransformer.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.*;
-
-abstract public class AbstractClassFilterTransformer extends AbstractClassTransformer {
-    private ClassTransformer pass;
-    private ClassVisitor target;
-
-    public void setTarget(ClassVisitor target) {
-        super.setTarget(target);
-        pass.setTarget(target);
-    }
-
-    protected AbstractClassFilterTransformer(ClassTransformer pass) {
-        this.pass = pass;
-    }
-
-    abstract protected boolean accept(int version, int access, String name, String signature, String superName, String[] interfaces);
-
-    public void visit(int version,
-                      int access,
-                      String name,
-                      String signature,
-                      String superName,
-                      String[] interfaces) {
-        target = accept(version, access, name, signature, superName, interfaces) ? pass : cv;
-        target.visit(version, access, name, signature, superName, interfaces);
-    }
-    
-    public void visitSource(String source, String debug) {
-        target.visitSource(source, debug);
-    }
-    
-    public void visitOuterClass(String owner, String name, String desc) {
-        target.visitOuterClass(owner, name, desc);
-    }
-    
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        return target.visitAnnotation(desc, visible);
-    }
-    
-    public void visitAttribute(Attribute attr) {
-        target.visitAttribute(attr);
-    }
-    
-    public void visitInnerClass(String name, String outerName, String innerName, int access) {
-        target.visitInnerClass(name, outerName, innerName, access);
-    }
-
-    public FieldVisitor visitField(int access,
-                                   String name,
-                                   String desc,
-                                   String signature,
-                                   Object value) {
-        return target.visitField(access, name, desc, signature, value);
-    }
-    
-    public MethodVisitor visitMethod(int access,
-                                     String name,
-                                     String desc,
-                                     String signature,
-                                     String[] exceptions) {
-        return target.visitMethod(access, name, desc, signature, exceptions);
-    }
-
-    public void visitEnd() {
-        target.visitEnd();
-        target = null; // just to be safe
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassLoader.java b/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassLoader.java
deleted file mode 100644
index 57846df..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassLoader.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.ClassReader;
-import org.mockito.asm.ClassWriter;
-import org.mockito.asm.util.*;
-import org.mockito.cglib.core.ClassGenerator;
-import org.mockito.cglib.core.CodeGenerationException;
-import org.mockito.cglib.core.DebuggingClassWriter;
-
-import java.io.IOException;
-
-abstract public class AbstractClassLoader extends ClassLoader {
-    private ClassFilter filter;
-    private ClassLoader classPath;
-    private static java.security.ProtectionDomain DOMAIN ;
-    
-    static{
-        
-        DOMAIN = (java.security.ProtectionDomain)
-        java.security.AccessController.doPrivileged(
-          new java.security.PrivilegedAction() {
-            public Object run() {
-               return AbstractClassLoader.class.getProtectionDomain();
-            }
-        }); 
-     }
-    
-    protected AbstractClassLoader(ClassLoader parent, ClassLoader classPath, ClassFilter filter) {
-        super(parent);
-        this.filter = filter;
-        this.classPath = classPath;
-    }
-
-    public Class loadClass(String name) throws ClassNotFoundException {
-        
-        Class loaded = findLoadedClass(name);
-        
-        if( loaded != null ){
-            if( loaded.getClassLoader() == this ){
-               return loaded;
-            }//else reload with this class loader
-        }
-        
-        if (!filter.accept(name)) {
-            return super.loadClass(name);
-        }
-        ClassReader r;
-        try {
-            
-           java.io.InputStream is = classPath.getResourceAsStream( 
-                       name.replace('.','/') + ".class"
-                  ); 
-           
-           if (is == null) {
-               
-              throw new ClassNotFoundException(name);
-              
-           }
-           try { 
-               
-              r = new ClassReader(is);
-            
-           } finally {
-               
-              is.close();
-             
-           }
-        } catch (IOException e) {
-            throw new ClassNotFoundException(name + ":" + e.getMessage());
-        }
-
-        try {
-            ClassWriter w =  new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
-            getGenerator(r).generateClass(w);
-            byte[] b = w.toByteArray();
-            Class c = super.defineClass(name, b, 0, b.length, DOMAIN);
-            postProcess(c);
-            return c;
-        } catch (RuntimeException e) {
-            throw e;
-        } catch (Error e) {
-            throw e;
-        } catch (Exception e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-
-    protected ClassGenerator getGenerator(ClassReader r) {
-        return new ClassReaderGenerator(r, attributes(), getFlags());
-    }
-
-    protected int getFlags() {
-        return 0;
-    }
-    
-    protected Attribute[] attributes() {
-        return null;
-    }
-
-    protected void postProcess(Class c) {
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassTransformer.java
deleted file mode 100644
index e157f95..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractClassTransformer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.ClassAdapter;
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.CodeGenerationException;
-
-abstract public class AbstractClassTransformer extends ClassAdapter implements ClassTransformer {
-    protected AbstractClassTransformer() {
-        super(null);
-    }
-
-    public void setTarget(ClassVisitor target) {
-        cv = target;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractProcessTask.java b/cglib-and-asm/src/org/mockito/cglib/transform/AbstractProcessTask.java
deleted file mode 100644
index a0437e7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractProcessTask.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import java.io.File;
-import java.util.*;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DirectoryScanner;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.types.FileSet;
-
-abstract public class AbstractProcessTask extends Task {
-    private Vector filesets = new Vector();
-
-    public void addFileset(FileSet set) {
-        filesets.addElement(set);
-    }
-    
-    protected Collection getFiles() {
-        Map fileMap = new HashMap();
-        Project p = getProject();
-        for (int i = 0; i < filesets.size(); i++) {
-            FileSet fs = (FileSet)filesets.elementAt(i);
-            DirectoryScanner ds = fs.getDirectoryScanner(p);
-            String[] srcFiles = ds.getIncludedFiles();
-            File dir = fs.getDir(p);
-            for (int j = 0; j < srcFiles.length; j++) {
-                 File src = new File(dir, srcFiles[j]);
-                 fileMap.put(src.getAbsolutePath(), src);
-            }
-        }
-        return fileMap.values();
-    }
-
-    
-    
-    public void execute() throws BuildException {
-        beforeExecute();
-        for (Iterator it = getFiles().iterator(); it.hasNext();) {
-            try {
-                processFile((File)it.next());
-            } catch (Exception e) {
-                 throw new BuildException(e);
-            }
-        }
-    }
-
-    protected void beforeExecute() throws BuildException { }
-    abstract protected void processFile(File file) throws Exception;
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractTransformTask.java b/cglib-and-asm/src/org/mockito/cglib/transform/AbstractTransformTask.java
deleted file mode 100644
index 48779c6..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/AbstractTransformTask.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.mockito.cglib.transform;
-
-import java.io.*;
-import java.net.MalformedURLException;
-import java.util.*;
-import java.util.zip.*;
-
-import org.apache.tools.ant.*;
-import org.mockito.asm.*;
-import org.mockito.cglib.core.*;
-
-abstract public class AbstractTransformTask extends AbstractProcessTask {
-    private static final int ZIP_MAGIC = 0x504B0304;
-
-    private static final int CLASS_MAGIC = 0xCAFEBABE;
-
-    private boolean verbose;
-
-    public void setVerbose(boolean verbose) {
-        this.verbose = verbose;
-    }
-
-    /**
-     * returns transformation for source class
-     * 
-     * @param classInfo
-     *            class information 
-     *            class name := classInfo[ 0 ] 
-     *            super class  name := classInfo[ 1 ]
-     *            interfaces := classInfo[ >1 ]
-     */
-    abstract protected ClassTransformer getClassTransformer(String[] classInfo);
-
-    protected Attribute[] attributes() {
-        return null;
-    }
-
-    protected void processFile(File file) throws Exception {
-
-        if (isClassFile(file)) {
-
-            processClassFile(file);
-
-        } else if (isJarFile(file)) {
-
-            processJarFile(file);
-
-        } else {
-            
-            log("ignoring " + file.toURL(), Project.MSG_WARN);
-            
-        }
-    }
-
-    /**
-     * @param file
-     * @throws Exception
-     * @throws FileNotFoundException
-     * @throws IOException
-     * @throws MalformedURLException
-     */
-    private void processClassFile(File file) throws Exception,
-            FileNotFoundException, IOException, MalformedURLException {
-
-        ClassReader reader = getClassReader(file);
-        String name[] = ClassNameReader.getClassInfo(reader);
-        ClassWriter w = new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
-        ClassTransformer t = getClassTransformer(name);
-        if (t != null) {
-
-            if (verbose) {
-                log("processing " + file.toURL());
-            }
-            new TransformingClassGenerator(new ClassReaderGenerator(
-                    getClassReader(file), attributes(), getFlags()), t)
-                    .generateClass(w);
-            FileOutputStream fos = new FileOutputStream(file);
-            try {
-                fos.write(w.toByteArray());
-            } finally {
-                fos.close();
-            }
-
-        }
-
-    }
-
-    protected int getFlags() {
-        return 0;
-    }
-
-    private static ClassReader getClassReader(File file) throws Exception {
-        InputStream in = new BufferedInputStream(new FileInputStream(file));
-        try {
-            ClassReader r = new ClassReader(in);
-            return r;
-        } finally {
-            in.close();
-        }
-
-    }
-
-    protected boolean isClassFile(File file) throws IOException {
-
-        return checkMagic(file, CLASS_MAGIC);
-
-    }
-
-    protected void processJarFile(File file) throws Exception {
-
-        if (verbose) {
-            log("processing " + file.toURL());
-        }
-        
-        File tempFile = File.createTempFile(file.getName(), null, new File(file
-                .getAbsoluteFile().getParent()));
-        try{
-            
-            ZipInputStream zip = new ZipInputStream(new FileInputStream(file));
-            try {
-                FileOutputStream fout = new FileOutputStream(tempFile, false);
-                try{
-                 ZipOutputStream out = new ZipOutputStream(fout);
-                                
-                    ZipEntry entry;
-                    while ((entry = zip.getNextEntry()) != null) {
-                        
-                        
-                        byte bytes[] = getBytes(zip);
-                        
-                        if (!entry.isDirectory()) {
-                            
-                            DataInputStream din = new DataInputStream(
-                                              new ByteArrayInputStream(bytes)
-                                            );
-                            
-                            if (din.readInt() == CLASS_MAGIC) {
-                                
-                                bytes = process(bytes);
-                                                        
-                            } else {
-                                if (verbose) {
-                                 log("ignoring " + entry.toString());
-                                }
-                            }
-                        }
-                       
-                        ZipEntry outEntry = new ZipEntry(entry.getName());
-                        outEntry.setMethod(entry.getMethod());
-                        outEntry.setComment(entry.getComment());
-                        outEntry.setSize(bytes.length);
-                        
-                        
-                        if(outEntry.getMethod() == ZipEntry.STORED){
-                            CRC32 crc = new CRC32();
-                            crc.update(bytes);
-                            outEntry.setCrc( crc.getValue() );
-                            outEntry.setCompressedSize(bytes.length);
-                        }
-                        out.putNextEntry(outEntry);
-                        out.write(bytes);
-                        out.closeEntry();
-                        zip.closeEntry();
-                        
-                    }
-                    out.close(); 
-                }finally{
-                 fout.close();    
-                } 
-            } finally {
-                zip.close();
-            }
-            
-            
-            if(file.delete()){
-                
-                File newFile = new File(tempFile.getAbsolutePath());
-                
-                if(!newFile.renameTo(file)){
-                    throw new IOException("can not rename " + tempFile + " to " + file);   
-                }
-                
-            }else{
-                throw new IOException("can not delete " + file);
-            }
-            
-        }finally{
-            
-            tempFile.delete();
-            
-        }
-        
-    }
-
-    /**
-     * @param bytes
-     * @return
-     * @throws IOException
-     * @throws Exception
-     */
-    private byte[] process(byte[] bytes) throws Exception {
-
-        ClassReader reader = new ClassReader(new ByteArrayInputStream(bytes));
-        String name[] = ClassNameReader.getClassInfo(reader);
-        ClassWriter w = new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
-        ClassTransformer t = getClassTransformer(name);
-        if (t != null) {
-            if (verbose) {
-                log("processing " + name[0]);
-            }
-            new TransformingClassGenerator(new ClassReaderGenerator(
-                    new ClassReader(new ByteArrayInputStream(bytes)),
-                    attributes(), getFlags()), t).generateClass(w);
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            out.write(w.toByteArray());
-            return out.toByteArray();
-        }
-        return bytes;
-    }
-
-    /**
-     * @param zip
-     * @return
-     * @throws IOException
-     */
-    private byte[] getBytes(ZipInputStream zip) throws IOException {
-
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        InputStream in = new BufferedInputStream(zip);
-        int b;
-        while ((b = in.read()) != -1) {
-            bout.write(b);
-        }
-        return bout.toByteArray();
-    }
-
-    private boolean checkMagic(File file, long magic) throws IOException {
-        DataInputStream in = new DataInputStream(new FileInputStream(file));
-        try {
-            int m = in.readInt();
-            return magic == m; 
-        } finally {
-            in.close();
-        }
-    }
-
-    protected boolean isJarFile(File file) throws IOException {
-        return checkMagic(file, ZIP_MAGIC);
-    }
-
-}
\ No newline at end of file
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/AnnotationVisitorTee.java b/cglib-and-asm/src/org/mockito/cglib/transform/AnnotationVisitorTee.java
deleted file mode 100644
index 3533440..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/AnnotationVisitorTee.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.AnnotationVisitor;
-
-public class AnnotationVisitorTee implements AnnotationVisitor {
-    private AnnotationVisitor av1, av2;
-
-    public static AnnotationVisitor getInstance(AnnotationVisitor av1, AnnotationVisitor av2) {
-        if (av1 == null)
-            return av2;
-        if (av2 == null)
-            return av1;
-        return new AnnotationVisitorTee(av1, av2);
-    }
-
-    public AnnotationVisitorTee(AnnotationVisitor av1, AnnotationVisitor av2) {
-        this.av1 = av1;
-        this.av2 = av2;
-    }
-
-    public void visit(String name, Object value) {
-        av2.visit(name, value);
-        av2.visit(name, value);
-    }
-    
-    public void visitEnum(String name, String desc, String value) {
-        av1.visitEnum(name, desc, value);
-        av2.visitEnum(name, desc, value);
-    }
-    
-    public AnnotationVisitor visitAnnotation(String name, String desc) {
-        return getInstance(av1.visitAnnotation(name, desc),
-                           av2.visitAnnotation(name, desc));
-    }
-    
-    public AnnotationVisitor visitArray(String name) {
-        return getInstance(av1.visitArray(name), av2.visitArray(name));
-    }
-    
-    public void visitEnd() {
-        av1.visitEnd();
-        av2.visitEnd();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassEmitterTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassEmitterTransformer.java
deleted file mode 100644
index 3c92d47..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassEmitterTransformer.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.cglib.core.ClassEmitter;
-
-abstract public class ClassEmitterTransformer extends ClassEmitter implements ClassTransformer {
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassFilter.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassFilter.java
deleted file mode 100644
index e453dfe..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassFilter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.mockito.cglib.transform;
-
-/**
- *
- * @author  baliuka
- */
-public interface ClassFilter {
-    
-    boolean accept(String className);
-    
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassFilterTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassFilterTransformer.java
deleted file mode 100644
index d9cdde2..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassFilterTransformer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.*;
-
-public class ClassFilterTransformer extends AbstractClassFilterTransformer {
-    private ClassFilter filter;
-
-    public ClassFilterTransformer(ClassFilter filter, ClassTransformer pass) {
-        super(pass);
-        this.filter = filter;
-    }
-
-    protected boolean accept(int version, int access, String name, String signature, String superName, String[] interfaces) {
-        return filter.accept(name.replace('/', '.'));
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassReaderGenerator.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassReaderGenerator.java
deleted file mode 100644
index c4b8be7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassReaderGenerator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.ClassReader;
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.ClassGenerator;
-
-public class ClassReaderGenerator implements ClassGenerator {
-    private final ClassReader r;
-    private final Attribute[] attrs;
-    private final int flags;
-    
-    public ClassReaderGenerator(ClassReader r, int flags) {
-        this(r, null, flags);
-    }
-
-    public ClassReaderGenerator(ClassReader r, Attribute[] attrs, int flags) {
-        this.r = r;
-        this.attrs = (attrs != null) ? attrs : new Attribute[0];
-        this.flags = flags;
-    }
-    
-    public void generateClass(ClassVisitor v) {
-        r.accept(v, attrs, flags);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformer.java
deleted file mode 100644
index 027cb26..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.ClassVisitor;
-
-public interface ClassTransformer extends ClassVisitor {
-    public void setTarget(ClassVisitor target);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerChain.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerChain.java
deleted file mode 100644
index 82f5a3b..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerChain.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.*;
-
-public class ClassTransformerChain extends AbstractClassTransformer {
-    private ClassTransformer[] chain;
-    
-    public ClassTransformerChain(ClassTransformer[] chain) {
-        this.chain = (ClassTransformer[])chain.clone();
-    }
-
-    public void setTarget(ClassVisitor v) {
-        super.setTarget(chain[0]);
-        ClassVisitor next = v;
-        for (int i = chain.length - 1; i >= 0; i--) {
-            chain[i].setTarget(next);
-            next = chain[i];
-        }
-    }
-
-    public MethodVisitor visitMethod(int access,
-                                     String name,
-                                     String desc,
-                                     String signature,
-                                     String[] exceptions) {
-        return cv.visitMethod(access, name, desc, signature, exceptions);
-    }
-
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append("ClassTransformerChain{");
-        for (int i = 0; i < chain.length; i++) {
-            if (i > 0) {
-                sb.append(", ");
-            }
-            sb.append(chain[i].toString());
-        }
-        sb.append("}");
-        return sb.toString();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerFactory.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerFactory.java
deleted file mode 100644
index d5b80b7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerFactory.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-public interface ClassTransformerFactory {
-    ClassTransformer newInstance();
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerTee.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerTee.java
deleted file mode 100644
index 64d90cb..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassTransformerTee.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.ClassAdapter;
-import org.mockito.asm.ClassVisitor;
-
-public class ClassTransformerTee extends ClassAdapter implements ClassTransformer {
-    private ClassVisitor branch;
-    
-    public ClassTransformerTee(ClassVisitor branch) {
-        super(null);
-        this.branch = branch;
-    }
-    
-    public void setTarget(ClassVisitor target) { 
-        cv = new ClassVisitorTee(branch, target);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/ClassVisitorTee.java b/cglib-and-asm/src/org/mockito/cglib/transform/ClassVisitorTee.java
deleted file mode 100644
index 6d4a016..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/ClassVisitorTee.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.*;
-
-public class ClassVisitorTee implements ClassVisitor {
-    private ClassVisitor cv1, cv2;
-    
-    public ClassVisitorTee(ClassVisitor cv1, ClassVisitor cv2) {
-        this.cv1 = cv1;
-        this.cv2 = cv2;
-    }
-
-    public void visit(int version,
-                      int access,
-                      String name,
-                      String signature,
-                      String superName,
-                      String[] interfaces) {
-        cv1.visit(version, access, name, signature, superName, interfaces);
-        cv2.visit(version, access, name, signature, superName, interfaces);
-    }
-
-    public void visitEnd() {
-        cv1.visitEnd();
-        cv2.visitEnd();
-        cv1 = cv2 = null;
-    }
-
-    public void visitInnerClass(String name, String outerName, String innerName, int access) {
-        cv1.visitInnerClass(name, outerName, innerName, access);
-        cv2.visitInnerClass(name, outerName, innerName, access);
-    }
-
-    public FieldVisitor visitField(int access,
-                                   String name,
-                                   String desc,
-                                   String signature,
-                                   Object value) {
-        FieldVisitor fv1 = cv1.visitField(access, name, desc, signature, value);
-        FieldVisitor fv2 = cv2.visitField(access, name, desc, signature, value);
-        if (fv1 == null)
-            return fv2;
-        if (fv2 == null)
-            return fv1;
-        return new FieldVisitorTee(fv1, fv2);
-    }
-
-
-    public MethodVisitor visitMethod(int access,
-                                     String name,
-                                     String desc,
-                                     String signature,
-                                     String[] exceptions) {
-        MethodVisitor mv1 = cv1.visitMethod(access, name, desc, signature, exceptions);
-        MethodVisitor mv2 = cv2.visitMethod(access, name, desc, signature, exceptions);
-        if (mv1 == null)
-            return mv2;
-        if (mv2 == null)
-            return mv1;
-        return new MethodVisitorTee(mv1, mv2);
-    }
-
-    public void visitSource(String source, String debug) {
-        cv1.visitSource(source, debug);
-        cv2.visitSource(source, debug);
-    }
-
-    public void visitOuterClass(String owner, String name, String desc) {
-        cv1.visitOuterClass(owner, name, desc);
-        cv2.visitOuterClass(owner, name, desc);
-    }
-
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        return AnnotationVisitorTee.getInstance(cv1.visitAnnotation(desc, visible),
-                                                cv2.visitAnnotation(desc, visible));
-    }
-    
-    public void visitAttribute(Attribute attrs) {
-        cv1.visitAttribute(attrs);
-        cv2.visitAttribute(attrs);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/FieldVisitorTee.java b/cglib-and-asm/src/org/mockito/cglib/transform/FieldVisitorTee.java
deleted file mode 100644
index f30e162..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/FieldVisitorTee.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.AnnotationVisitor;
-import org.mockito.asm.Attribute;
-import org.mockito.asm.FieldVisitor;
-
-public class FieldVisitorTee implements FieldVisitor {
-    private FieldVisitor fv1, fv2;
-    
-    public FieldVisitorTee(FieldVisitor fv1, FieldVisitor fv2) {
-        this.fv1 = fv1;
-        this.fv2 = fv2;
-    }
-
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        return AnnotationVisitorTee.getInstance(fv1.visitAnnotation(desc, visible),
-                                                fv2.visitAnnotation(desc, visible));
-    }
-    
-    public void visitAttribute(Attribute attr) {
-        fv1.visitAttribute(attr);
-        fv2.visitAttribute(attr);
-    }
-
-    public void visitEnd() {
-        fv1.visitEnd();
-        fv2.visitEnd();
-    }
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/MethodFilter.java b/cglib-and-asm/src/org/mockito/cglib/transform/MethodFilter.java
deleted file mode 100644
index 667d3c3..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/MethodFilter.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.Attribute;
-
-public interface MethodFilter {
-    // TODO: pass class name too?
-    boolean accept(int access, String name, String desc, String signature, String[] exceptions);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/MethodFilterTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/MethodFilterTransformer.java
deleted file mode 100644
index 90e13c7..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/MethodFilterTransformer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.*;
-
-public class MethodFilterTransformer extends AbstractClassTransformer {
-    private MethodFilter filter;
-    private ClassTransformer pass;
-    private ClassVisitor direct;
-    
-    public MethodFilterTransformer(MethodFilter filter, ClassTransformer pass) {
-        this.filter = filter;
-        this.pass = pass;
-        super.setTarget(pass);
-    }
-
-    public MethodVisitor visitMethod(int access,
-                                     String name,
-                                     String desc,
-                                     String signature,
-                                     String[] exceptions) {
-        return (filter.accept(access, name, desc, signature, exceptions) ? pass : direct).visitMethod(access, name, desc, signature, exceptions);
-    }
-    
-    public void setTarget(ClassVisitor target) {
-        pass.setTarget(target);
-        direct = target;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/MethodVisitorTee.java b/cglib-and-asm/src/org/mockito/cglib/transform/MethodVisitorTee.java
deleted file mode 100644
index 9f44a7f..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/MethodVisitorTee.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.*;
-
-public class MethodVisitorTee implements MethodVisitor {
-    private final MethodVisitor mv1;
-    private final MethodVisitor mv2;
-    
-    public MethodVisitorTee(MethodVisitor mv1, MethodVisitor mv2) {
-        this.mv1 = mv1;
-        this.mv2 = mv2;
-    }
-
-    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
-        mv1.visitFrame(type, nLocal, local, nStack, stack);
-        mv2.visitFrame(type, nLocal, local, nStack, stack);
-    }
-
-    public AnnotationVisitor visitAnnotationDefault() {
-        return AnnotationVisitorTee.getInstance(mv1.visitAnnotationDefault(),
-                                                mv2.visitAnnotationDefault());
-    }
-    
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        return AnnotationVisitorTee.getInstance(mv1.visitAnnotation(desc, visible),
-                                                mv2.visitAnnotation(desc, visible));
-    }
-    
-    public AnnotationVisitor visitParameterAnnotation(int parameter,
-                                                      String desc,
-                                                      boolean visible) {
-        return AnnotationVisitorTee.getInstance(mv1.visitParameterAnnotation(parameter, desc, visible),
-                                                mv2.visitParameterAnnotation(parameter, desc, visible));
-    }
-
-    public void visitAttribute(Attribute attr) {
-        mv1.visitAttribute(attr);
-        mv2.visitAttribute(attr);
-    }
-    
-    public void visitCode() {
-        mv1.visitCode();
-        mv2.visitCode();
-    }
-    
-    public void visitInsn(int opcode) {
-        mv1.visitInsn(opcode);
-        mv2.visitInsn(opcode);
-    }
-    
-    public void visitIntInsn(int opcode, int operand) {
-        mv1.visitIntInsn(opcode, operand);
-        mv2.visitIntInsn(opcode, operand);
-    }
-    
-    public void visitVarInsn(int opcode, int var) {
-        mv1.visitVarInsn(opcode, var);
-        mv2.visitVarInsn(opcode, var);
-    }
-    
-    public void visitTypeInsn(int opcode, String desc) {
-        mv1.visitTypeInsn(opcode, desc);
-        mv2.visitTypeInsn(opcode, desc);
-    }
-    
-    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-        mv1.visitFieldInsn(opcode, owner, name, desc);
-        mv2.visitFieldInsn(opcode, owner, name, desc);
-    }
-    
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-        mv1.visitMethodInsn(opcode, owner, name, desc);
-        mv2.visitMethodInsn(opcode, owner, name, desc);
-    }
-    
-    public void visitJumpInsn(int opcode, Label label) {
-        mv1.visitJumpInsn(opcode, label);
-        mv2.visitJumpInsn(opcode, label);
-    }
-    
-    public void visitLabel(Label label) {
-        mv1.visitLabel(label);
-        mv2.visitLabel(label);
-    }
-    
-    public void visitLdcInsn(Object cst) {
-        mv1.visitLdcInsn(cst);
-        mv2.visitLdcInsn(cst);
-    }
-    
-    public void visitIincInsn(int var, int increment) {
-        mv1.visitIincInsn(var, increment);
-        mv2.visitIincInsn(var, increment);
-    }
-    
-    public void visitTableSwitchInsn(int min, int max, Label dflt, Label labels[]) {
-        mv1.visitTableSwitchInsn(min, max, dflt, labels);
-        mv2.visitTableSwitchInsn(min, max, dflt, labels);
-    }
-    
-    public void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]) {
-        mv1.visitLookupSwitchInsn(dflt, keys, labels);
-        mv2.visitLookupSwitchInsn(dflt, keys, labels);
-    }
-    
-    public void visitMultiANewArrayInsn(String desc, int dims) {
-        mv1.visitMultiANewArrayInsn(desc, dims);
-        mv2.visitMultiANewArrayInsn(desc, dims);
-    }
-    
-    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
-        mv1.visitTryCatchBlock(start, end, handler, type);
-        mv2.visitTryCatchBlock(start, end, handler, type);
-    }
-    
-    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
-        mv1.visitLocalVariable(name, desc, signature, start, end, index);
-        mv2.visitLocalVariable(name, desc, signature, start, end, index);
-    }
-    
-    public void visitLineNumber(int line, Label start) {
-        mv1.visitLineNumber(line, start);
-        mv2.visitLineNumber(line, start);
-    }
-    
-    public void visitMaxs(int maxStack, int maxLocals) {
-        mv1.visitMaxs(maxStack, maxLocals);
-        mv2.visitMaxs(maxStack, maxLocals);
-    }
-    
-    public void visitEnd() {
-        mv1.visitEnd();
-        mv2.visitEnd();
-    }
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/TransformingClassGenerator.java b/cglib-and-asm/src/org/mockito/cglib/transform/TransformingClassGenerator.java
deleted file mode 100644
index 722e88f..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/TransformingClassGenerator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.ClassGenerator;
-import org.mockito.cglib.core.Transformer;
-
-public class TransformingClassGenerator implements ClassGenerator {
-    private ClassGenerator gen;
-    private ClassTransformer t;
-    
-    public TransformingClassGenerator(ClassGenerator gen, ClassTransformer t) {
-        this.gen = gen;
-        this.t = t;
-    }
-    
-    public void generateClass(ClassVisitor v) throws Exception {
-        t.setTarget(v);
-        gen.generateClass(t);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/TransformingClassLoader.java b/cglib-and-asm/src/org/mockito/cglib/transform/TransformingClassLoader.java
deleted file mode 100644
index a628649..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/TransformingClassLoader.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform;
-
-import java.util.*;
-
-import org.mockito.asm.*;
-import org.mockito.cglib.core.ClassGenerator;
-
-public class TransformingClassLoader extends AbstractClassLoader {
-    private ClassTransformerFactory t;
-    
-    public TransformingClassLoader(ClassLoader parent, ClassFilter filter, ClassTransformerFactory t) {
-        super(parent, parent, filter);
-        this.t = t;
-    }
-
-    protected ClassGenerator getGenerator(ClassReader r) {
-        ClassTransformer t2 = (ClassTransformer)t.newInstance();
-        return new TransformingClassGenerator(super.getGenerator(r), t2);
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AbstractInterceptFieldCallback.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/AbstractInterceptFieldCallback.java
deleted file mode 100644
index 0baee23..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AbstractInterceptFieldCallback.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-/**
- * @author Chris Nokleberg
- */
-public class AbstractInterceptFieldCallback implements InterceptFieldCallback {
-    
-    public int writeInt(Object obj, String name, int oldValue, int newValue) { return newValue; }
-    public char writeChar(Object obj, String name, char oldValue, char newValue) { return newValue; }
-    public byte writeByte(Object obj, String name, byte oldValue, byte newValue) { return newValue; }
-    public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) { return newValue; }
-    public short writeShort(Object obj, String name, short oldValue, short newValue) { return newValue; }
-    public float writeFloat(Object obj, String name, float oldValue, float newValue) { return newValue; }
-    public double writeDouble(Object obj, String name, double oldValue, double newValue) { return newValue; }
-    public long writeLong(Object obj, String name, long oldValue, long newValue) { return newValue; }
-    public Object writeObject(Object obj, String name, Object oldValue, Object newValue) { return newValue; }
-
-    public int readInt(Object obj, String name, int oldValue) { return oldValue; }
-    public char readChar(Object obj, String name, char oldValue) { return oldValue; }
-    public byte readByte(Object obj, String name, byte oldValue) { return oldValue; }
-    public boolean readBoolean(Object obj, String name, boolean oldValue) { return oldValue; }
-    public short readShort(Object obj, String name, short oldValue) { return oldValue; }
-    public float readFloat(Object obj, String name, float oldValue) { return oldValue; }
-    public double readDouble(Object obj, String name, double oldValue) { return oldValue; }
-    public long readLong(Object obj, String name, long oldValue) { return oldValue; }
-    public Object readObject(Object obj, String name, Object oldValue) { return oldValue; }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AccessFieldTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/AccessFieldTransformer.java
deleted file mode 100644
index ec81215..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AccessFieldTransformer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.MethodVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-public class AccessFieldTransformer extends ClassEmitterTransformer {
-    private Callback callback;
-
-    public AccessFieldTransformer(Callback callback) {
-        this.callback = callback;
-    }
-
-    public interface Callback {
-        String getPropertyName(Type owner, String fieldName);
-    }
-
-    public void declare_field(int access, final String name, Type type, Object value) {
-        super.declare_field(access, name, type, value);
-
-        String property = TypeUtils.upperFirst(callback.getPropertyName(getClassType(), name));
-        if (property != null) {
-            CodeEmitter e;
-            e = begin_method(Constants.ACC_PUBLIC,
-                             new Signature("get" + property,
-                                           type,
-                                           Constants.TYPES_EMPTY),
-                             null);
-            e.load_this();
-            e.getfield(name);
-            e.return_value();
-            e.end_method();
-
-            e = begin_method(Constants.ACC_PUBLIC,
-                             new Signature("set" + property,
-                                           Type.VOID_TYPE,
-                                           new Type[]{ type }),
-                             null);
-            e.load_this();
-            e.load_arg(0);
-            e.putfield(name);
-            e.return_value();
-            e.end_method();
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddDelegateTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddDelegateTransformer.java
deleted file mode 100644
index 6c39ddd..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddDelegateTransformer.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-/**
- * @author Juozas Baliuka
- */
-public class AddDelegateTransformer extends ClassEmitterTransformer {
-    private static final String DELEGATE = "$CGLIB_DELEGATE";
-    private static final Signature CSTRUCT_OBJECT =
-      TypeUtils.parseSignature("void <init>(Object)");
-    
-    private Class[] delegateIf;
-    private Class delegateImpl;
-    private Type delegateType;
-    
-    /** Creates a new instance of AddDelegateTransformer */
-    public AddDelegateTransformer(Class delegateIf[], Class delegateImpl) {
-        try {
-            delegateImpl.getConstructor(new Class[]{ Object.class });
-            this.delegateIf = delegateIf;
-            this.delegateImpl = delegateImpl;
-            delegateType = Type.getType(delegateImpl);
-        } catch (NoSuchMethodException e) {
-            throw new CodeGenerationException(e);
-        }
-    }
-    
-    public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) {
-        
-        if(!TypeUtils.isInterface(access)){
-            
-        Type[] all = TypeUtils.add(interfaces, TypeUtils.getTypes(delegateIf));
-        super.begin_class(version, access, className, superType, all, sourceFile);
-        
-        declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT,
-                      DELEGATE,
-                      delegateType,
-                      null);
-        for (int i = 0; i < delegateIf.length; i++) {
-            Method[] methods = delegateIf[i].getMethods();
-            for (int j = 0; j < methods.length; j++) {
-                if (Modifier.isAbstract(methods[j].getModifiers())) {
-                    addDelegate(methods[j]);
-                }
-            }
-        }
-        }else{
-           super.begin_class(version, access, className, superType, interfaces, sourceFile);
-        }
-    }
-
-    public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
-        final CodeEmitter e = super.begin_method(access, sig, exceptions);
-        if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
-            return new CodeEmitter(e) {
-                private boolean transformInit = true;
-                public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-                    super.visitMethodInsn(opcode, owner, name, desc);
-                    if (transformInit && opcode == Constants.INVOKESPECIAL) {
-                        load_this();
-                        new_instance(delegateType);
-                        dup();
-                        load_this();
-                        invoke_constructor(delegateType, CSTRUCT_OBJECT);
-                        putfield(DELEGATE);
-                        transformInit = false;
-                    }
-                }
-            };
-        }
-        return e;
-    }
-
-    private void addDelegate(Method m) {
-        Method delegate;
-        try {
-            delegate = delegateImpl.getMethod(m.getName(), m.getParameterTypes());
-            if (!delegate.getReturnType().getName().equals(m.getReturnType().getName())){
-                throw new IllegalArgumentException("Invalid delegate signature " + delegate);
-            }
-        } catch (NoSuchMethodException e) {
-            throw new CodeGenerationException(e);
-        }
-
-        final Signature sig = ReflectUtils.getSignature(m);
-        Type[] exceptions = TypeUtils.getTypes(m.getExceptionTypes());
-        CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, sig, exceptions);
-        e.load_this();
-        e.getfield(DELEGATE);
-        e.load_args();
-        e.invoke_virtual(delegateType, sig);
-        e.return_value();
-        e.end_method();
-    }
-}
-
-
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddInitTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddInitTransformer.java
deleted file mode 100644
index b403c7d..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddInitTransformer.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import java.lang.reflect.Method;
-
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.CodeEmitter;
-import org.mockito.cglib.core.Constants;
-import org.mockito.cglib.core.MethodInfo;
-import org.mockito.cglib.core.ReflectUtils;
-import org.mockito.cglib.core.Signature;
-import org.mockito.cglib.transform.ClassEmitterTransformer;
-
-/**
- * @author	Mark Hobson
- */
-public class AddInitTransformer extends ClassEmitterTransformer {
-    private MethodInfo info;
-    
-    public AddInitTransformer(Method method) {
-        info = ReflectUtils.getMethodInfo(method);
-        
-        Type[] types = info.getSignature().getArgumentTypes();
-        if (types.length != 1 ||
-        !types[0].equals(Constants.TYPE_OBJECT) ||
-        !info.getSignature().getReturnType().equals(Type.VOID_TYPE)) {
-            throw new IllegalArgumentException(method + " illegal signature");
-        }
-    }
-    
-    public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
-        final CodeEmitter emitter = super.begin_method(access, sig, exceptions);
-        if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
-            return new CodeEmitter(emitter) {
-                public void visitInsn(int opcode) {
-                    if (opcode == Constants.RETURN) {
-                        load_this();
-                        invoke(info);
-                    }
-                    super.visitInsn(opcode);
-                }
-            };
-        }
-        return emitter;
-    }
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddPropertyTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddPropertyTransformer.java
deleted file mode 100644
index 49ada76..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddPropertyTransformer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import java.util.*;
-
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-public class AddPropertyTransformer extends ClassEmitterTransformer {
-    private final String[] names;
-    private final Type[] types;
-
-    public AddPropertyTransformer(Map props) {
-        int size = props.size();
-        names = (String[])props.keySet().toArray(new String[size]);
-        types = new Type[size];
-        for (int i = 0; i < size; i++) {
-            types[i] = (Type)props.get(names[i]);
-        }
-    }
-
-    public AddPropertyTransformer(String[] names, Type[] types) {
-        this.names = names;
-        this.types = types;
-    }
-
-    public void end_class() {
-        if (!TypeUtils.isAbstract(getAccess())) {
-            EmitUtils.add_properties(this, names, types);
-        }
-        super.end_class();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddStaticInitTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddStaticInitTransformer.java
deleted file mode 100644
index 1753b2a..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/AddStaticInitTransformer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2003,2004 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import java.lang.reflect.Method;
-
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-/**
- * @author Juozas Baliuka, Chris Nokleberg
- */
-public class AddStaticInitTransformer extends ClassEmitterTransformer {
-    private MethodInfo info;
-
-    public AddStaticInitTransformer(Method classInit) {
-        info = ReflectUtils.getMethodInfo(classInit);
-        if (!TypeUtils.isStatic(info.getModifiers())) {
-            throw new IllegalArgumentException(classInit + " is not static");
-        }
-        Type[] types = info.getSignature().getArgumentTypes();
-        if (types.length != 1 ||
-            !types[0].equals(Constants.TYPE_CLASS) ||
-            !info.getSignature().getReturnType().equals(Type.VOID_TYPE)) {
-            throw new IllegalArgumentException(classInit + " illegal signature");
-        }
-    }
-
-    protected void init() {
-        if (!TypeUtils.isInterface(getAccess())) {
-            CodeEmitter e = getStaticHook();
-            EmitUtils.load_class_this(e);
-            e.invoke(info);
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/FieldProvider.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/FieldProvider.java
deleted file mode 100644
index 315e7e5..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/FieldProvider.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-public interface FieldProvider {
-    
-    String[] getFieldNames();
-    
-    Class[]  getFieldTypes();
-    
-    void setField(int index, Object value);
-    
-    Object getField(int index);
-    
-    
-    void setField(String name, Object value);
-    
-    Object getField(String name);
-    
-    
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/FieldProviderTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/FieldProviderTransformer.java
deleted file mode 100644
index 8695069..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/FieldProviderTransformer.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import java.util.*;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-public class FieldProviderTransformer extends ClassEmitterTransformer {
-    
-    private static final String FIELD_NAMES = "CGLIB$FIELD_NAMES";
-    private static final String FIELD_TYPES = "CGLIB$FIELD_TYPES";
-    
-    private static final Type FIELD_PROVIDER =
-      TypeUtils.parseType("org.mockito.cglib.transform.impl.FieldProvider");
-    private static final Type ILLEGAL_ARGUMENT_EXCEPTION =
-      TypeUtils.parseType("IllegalArgumentException");
-    private static final Signature PROVIDER_GET =
-      TypeUtils.parseSignature("Object getField(String)");
-    private static final Signature PROVIDER_SET =
-      TypeUtils.parseSignature("void setField(String, Object)");
-    private static final Signature PROVIDER_SET_BY_INDEX =
-      TypeUtils.parseSignature("void setField(int, Object)");
-    private static final Signature PROVIDER_GET_BY_INDEX =
-      TypeUtils.parseSignature("Object getField(int)");
-    private static final Signature PROVIDER_GET_TYPES =
-      TypeUtils.parseSignature("Class[] getFieldTypes()");
-    private static final Signature PROVIDER_GET_NAMES =
-      TypeUtils.parseSignature("String[] getFieldNames()");
-    
-    private int access;
-    private Map fields;
-    
-    public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) {
-        if (!TypeUtils.isAbstract(access)) {
-            interfaces = TypeUtils.add(interfaces, FIELD_PROVIDER);
-        }
-        this.access = access;
-        fields = new HashMap();
-        super.begin_class(version, access, className, superType, interfaces, sourceFile);
-    }
-
-    public void declare_field(int access, String name, Type type, Object value) {
-        super.declare_field(access, name, type, value);
-        
-        if (!TypeUtils.isStatic(access)) {
-            fields.put(name, type);
-        }
-    }
-
-    public void end_class() {
-        if (!TypeUtils.isInterface(access)) {  
-            try {
-                generate();
-            } catch (RuntimeException e) {
-                throw e;
-            } catch (Exception e) {
-                throw new CodeGenerationException(e);
-            }
-        }
-        super.end_class();
-    }
-
-    private void generate() throws Exception {
-        final String[] names = (String[])fields.keySet().toArray(new String[fields.size()]);
-
-        int indexes[] = new int[names.length];
-        for (int i = 0; i < indexes.length; i++) {
-            indexes[i] = i;
-        }
-        
-        super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_NAMES, Constants.TYPE_STRING_ARRAY, null);
-        super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_TYPES, Constants.TYPE_CLASS_ARRAY, null);
-
-        // use separate methods here because each process switch inner class needs a final CodeEmitter
-        initFieldProvider(names);
-        getNames();
-        getTypes();
-        getField(names);
-        setField(names);
-        setByIndex(names, indexes);
-        getByIndex(names, indexes);
-    }
-
-    private void initFieldProvider(String[] names) {
-        CodeEmitter e = getStaticHook();
-        EmitUtils.push_object(e, names);
-        e.putstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY);
-        
-        e.push(names.length);
-        e.newarray(Constants.TYPE_CLASS);
-        e.dup();
-        for(int i = 0; i < names.length; i++ ){ 
-            e.dup();
-            e.push(i);
-            Type type = (Type)fields.get(names[i]);
-            EmitUtils.load_class(e, type);
-            e.aastore();
-        }
-        e.putstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY);
-    }
-
-    private void getNames() {
-        CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_NAMES, null);
-        e.getstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY);
-        e.return_value();
-        e.end_method();
-    }
-
-    private void getTypes() {
-        CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_TYPES, null);
-        e.getstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY);
-        e.return_value();
-        e.end_method();
-    }
-
-    private void setByIndex(final String[] names, final int[] indexes) throws Exception {
-        final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_SET_BY_INDEX, null);
-        e.load_this();
-        e.load_arg(1);
-        e.load_arg(0);
-        e.process_switch(indexes, new ProcessSwitchCallback() {
-            public void processCase(int key, Label end) throws Exception {
-                Type type = (Type)fields.get(names[key]);
-                e.unbox(type);
-                e.putfield(names[key]);
-                e.return_value();
-            }
-            public void processDefault() throws Exception {
-                e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index");         
-            }
-        });
-        e.end_method();
-    }
-
-    private void getByIndex(final String[] names, final int[] indexes) throws Exception {
-        final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_BY_INDEX, null);
-        e.load_this();
-        e.load_arg(0);
-        e.process_switch(indexes, new ProcessSwitchCallback() {
-            public void processCase(int key, Label end) throws Exception {
-                Type type = (Type)fields.get(names[key]);
-                e.getfield(names[key]);
-                e.box(type);
-                e.return_value();
-            }
-            public void processDefault() throws Exception {
-                e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index");         
-            }
-        });
-        e.end_method();
-    }
-
-    // TODO: if this is used to enhance class files SWITCH_STYLE_TRIE should be used
-    // to avoid JVM hashcode implementation incompatibilities
-    private void getField(String[] names) throws Exception {
-        final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_GET, null);
-        e.load_this();
-        e.load_arg(0);
-        EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                Type type = (Type)fields.get(key);
-                e.getfield((String)key);
-                e.box(type);
-                e.return_value();
-            }
-            public void processDefault() {
-                e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name");
-            }
-        });
-        e.end_method();
-    }
-
-    private void setField(String[] names) throws Exception {
-        final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_SET, null);
-        e.load_this();
-        e.load_arg(1);
-        e.load_arg(0);
-        EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
-            public void processCase(Object key, Label end) {
-                Type type = (Type)fields.get(key);
-                e.unbox(type);
-                e.putfield((String)key);
-                e.return_value();
-            }
-            public void processDefault() {
-                e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name");
-            }
-        });
-        e.end_method();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldCallback.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldCallback.java
deleted file mode 100644
index 06d4140..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldCallback.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-/**
- * @author Juozas Baliuka
- */
-public interface InterceptFieldCallback {
-    
-    int writeInt(Object obj, String name, int oldValue, int newValue);
-    char writeChar(Object obj, String name, char oldValue, char newValue);
-    byte writeByte(Object obj, String name, byte oldValue, byte newValue);
-    boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue);
-    short writeShort(Object obj, String name, short oldValue, short newValue);
-    float writeFloat(Object obj, String name, float oldValue, float newValue);
-    double writeDouble(Object obj, String name, double oldValue, double newValue);
-    long writeLong(Object obj, String name, long oldValue, long newValue);
-    Object writeObject(Object obj, String name, Object oldValue, Object newValue);
-
-    int readInt(Object obj, String name, int oldValue);
-    char readChar(Object obj, String name, char oldValue);
-    byte readByte(Object obj, String name, byte oldValue);
-    boolean readBoolean(Object obj, String name, boolean oldValue);
-    short readShort(Object obj, String name, short oldValue);
-    float readFloat(Object obj, String name, float oldValue);
-    double readDouble(Object obj, String name, double oldValue);
-    long readLong(Object obj, String name, long oldValue);
-    Object readObject(Object obj, String name, Object oldValue);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldEnabled.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldEnabled.java
deleted file mode 100644
index bd92045..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldEnabled.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-public interface InterceptFieldEnabled {
-    void setInterceptFieldCallback(InterceptFieldCallback callback);
-    InterceptFieldCallback getInterceptFieldCallback();
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldFilter.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldFilter.java
deleted file mode 100644
index 31d4c1e..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldFilter.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import org.mockito.asm.Type;
-
-public interface InterceptFieldFilter {
-    boolean acceptRead(Type owner, String name);
-    boolean acceptWrite(Type owner, String name);
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldTransformer.java
deleted file mode 100644
index 180571f..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/InterceptFieldTransformer.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Label;
-import org.mockito.asm.MethodAdapter;
-import org.mockito.asm.MethodVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-/**
- * @author Juozas Baliuka, Chris Nokleberg
- */
-public class InterceptFieldTransformer extends ClassEmitterTransformer {
-    private static final String CALLBACK_FIELD = "$CGLIB_READ_WRITE_CALLBACK";
-    private static final Type CALLBACK =
-      TypeUtils.parseType("org.mockito.cglib.transform.impl.InterceptFieldCallback");
-    private static final Type ENABLED =
-      TypeUtils.parseType("org.mockito.cglib.transform.impl.InterceptFieldEnabled");
-    private static final Signature ENABLED_SET =
-      new Signature("setInterceptFieldCallback", Type.VOID_TYPE, new Type[]{ CALLBACK });
-    private static final Signature ENABLED_GET =
-      new Signature("getInterceptFieldCallback", CALLBACK, new Type[0]);
-
-    private InterceptFieldFilter filter;
-    
-    public InterceptFieldTransformer(InterceptFieldFilter filter) {
-        this.filter = filter;
-    }
-    
-    public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) {
-        if (!TypeUtils.isInterface(access)) {
-            super.begin_class(version, access, className, superType, TypeUtils.add(interfaces, ENABLED), sourceFile);
-                    
-            super.declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT,
-                                CALLBACK_FIELD,
-                                CALLBACK,
-                                null);
-
-            CodeEmitter e;
-            e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_GET, null);
-            e.load_this();
-            e.getfield(CALLBACK_FIELD);
-            e.return_value();
-            e.end_method();
-                
-            e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_SET, null);
-            e.load_this();
-            e.load_arg(0);
-            e.putfield(CALLBACK_FIELD);
-            e.return_value();
-            e.end_method();
-        } else {
-            super.begin_class(version, access, className, superType, interfaces, sourceFile);
-        }
-    }
-
-    public void declare_field(int access, String name, Type type, Object value) {
-        super.declare_field(access, name, type, value);
-        if (!TypeUtils.isStatic(access)) {
-            if (filter.acceptRead(getClassType(), name)) {
-                addReadMethod(name, type);
-            }
-            if (filter.acceptWrite(getClassType(), name)) {
-                addWriteMethod(name, type);
-            }
-        }
-    }
-
-    private void addReadMethod(String name, Type type) {
-        CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC,
-                                           readMethodSig(name, type.getDescriptor()),
-                                           null);
-        e.load_this();
-        e.getfield(name);
-        e.load_this();
-        e.invoke_interface(ENABLED,ENABLED_GET);
-        Label intercept = e.make_label();
-        e.ifnonnull(intercept);
-        e.return_value();
-
-        e.mark(intercept);
-        Local result = e.make_local(type);
-        e.store_local(result);
-        e.load_this();
-        e.invoke_interface(ENABLED,ENABLED_GET);
-        e.load_this();
-        e.push(name);
-        e.load_local(result);
-        e.invoke_interface(CALLBACK, readCallbackSig(type));
-        if (!TypeUtils.isPrimitive(type)) {
-            e.checkcast(type);
-        }
-        e.return_value();
-        e.end_method();
-    }
-
-    private void addWriteMethod(String name, Type type) {
-        CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC,
-                                           writeMethodSig(name, type.getDescriptor()),
-                                           null);
-        e.load_this();
-        e.dup();
-        e.invoke_interface(ENABLED,ENABLED_GET);
-        Label skip = e.make_label();
-        e.ifnull(skip);
-
-        e.load_this();
-        e.invoke_interface(ENABLED,ENABLED_GET);
-        e.load_this();
-        e.push(name);
-        e.load_this();
-        e.getfield(name);
-        e.load_arg(0);
-        e.invoke_interface(CALLBACK, writeCallbackSig(type));
-        if (!TypeUtils.isPrimitive(type)) {
-            e.checkcast(type);
-        }
-        Label go = e.make_label();
-        e.goTo(go);
-        e.mark(skip);
-        e.load_arg(0);
-        e.mark(go);
-        e.putfield(name);
-        e.return_value();
-        e.end_method();
-    }
-                
-    public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
-        return new CodeEmitter(super.begin_method(access, sig, exceptions)) {
-            public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-                Type towner = TypeUtils.fromInternalName(owner);
-                switch (opcode) {
-                case Constants.GETFIELD:
-                    if (filter.acceptRead(towner, name)) {
-                        helper(towner, readMethodSig(name, desc));
-                        return;
-                    }
-                    break;
-                case Constants.PUTFIELD:
-                    if (filter.acceptWrite(towner, name)) {
-                        helper(towner, writeMethodSig(name, desc));
-                        return;
-                    }
-                    break;
-                }
-                super.visitFieldInsn(opcode, owner, name, desc);
-            }
-
-            private void helper(Type owner, Signature sig) {
-                invoke_virtual(owner, sig);
-            }
-        };
-    }
-
-    private static Signature readMethodSig(String name, String desc) {
-        return new Signature("$cglib_read_" + name, "()" + desc);
-    }
-
-    private static Signature writeMethodSig(String name, String desc) {
-        return new Signature("$cglib_write_" + name, "(" + desc + ")V");
-    }
-
-    private static Signature readCallbackSig(Type type) {
-        Type remap = remap(type);
-        return new Signature("read" + callbackName(remap),
-                             remap,
-                             new Type[]{ Constants.TYPE_OBJECT,
-                                         Constants.TYPE_STRING,
-                                         remap });
-    }
-
-    private static Signature writeCallbackSig(Type type) {
-        Type remap = remap(type);
-        return new Signature("write" + callbackName(remap),
-                             remap,
-                             new Type[]{ Constants.TYPE_OBJECT,
-                                         Constants.TYPE_STRING,
-                                         remap,
-                                         remap });
-    }
-
-    private static Type remap(Type type) {
-        switch (type.getSort()) {
-        case Type.OBJECT:
-        case Type.ARRAY:
-            return Constants.TYPE_OBJECT;
-        default:
-            return type;
-        }
-    }
-
-    private static String callbackName(Type type) {
-        return (type == Constants.TYPE_OBJECT) ?
-            "Object" :
-            TypeUtils.upperFirst(TypeUtils.getClassName(type));
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/UndeclaredThrowableStrategy.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/UndeclaredThrowableStrategy.java
deleted file mode 100644
index 2c1b271..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/UndeclaredThrowableStrategy.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import org.mockito.asm.Attribute;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-/**
- * A {@link GeneratorStrategy} suitable for use with {@link org.mockito.cglib.Enhancer} which
- * causes all undeclared exceptions thrown from within a proxied method to be wrapped
- * in an alternative exception of your choice.
- */
-public class UndeclaredThrowableStrategy extends DefaultGeneratorStrategy {
-    private ClassTransformer t;
-
-    /**
-     * Create a new instance of this strategy.
-     * @param wrapper a class which extends either directly or
-     * indirectly from <code>Throwable</code> and which has at least one
-     * constructor that takes a single argument of type
-     * <code>Throwable</code>, for example
-     * <code>java.lang.reflect.UndeclaredThrowableException.class</code>
-     */
-    public UndeclaredThrowableStrategy(Class wrapper) {
-        t = new UndeclaredThrowableTransformer(wrapper);
-        t = new MethodFilterTransformer(TRANSFORM_FILTER, t);
-    }
-    
-    private static final MethodFilter TRANSFORM_FILTER = new MethodFilter() {
-        public boolean accept(int access, String name, String desc, String signature, String[] exceptions) {
-            return !TypeUtils.isPrivate(access) && name.indexOf('$') < 0;
-        }
-    };
-
-    protected ClassGenerator transform(ClassGenerator cg) throws Exception {
-        return new TransformingClassGenerator(cg, t);
-    }
-}
-
diff --git a/cglib-and-asm/src/org/mockito/cglib/transform/impl/UndeclaredThrowableTransformer.java b/cglib-and-asm/src/org/mockito/cglib/transform/impl/UndeclaredThrowableTransformer.java
deleted file mode 100644
index 09ff741..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/transform/impl/UndeclaredThrowableTransformer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.transform.impl;
-
-import java.lang.reflect.Constructor;
-
-import org.mockito.asm.Attribute;
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-import org.mockito.cglib.transform.*;
-
-public class UndeclaredThrowableTransformer extends ClassEmitterTransformer {
-    private Type wrapper;
-
-    public UndeclaredThrowableTransformer(Class wrapper) {
-        this.wrapper = Type.getType(wrapper);
-        boolean found = false;
-        Constructor[] cstructs = wrapper.getConstructors();
-        for (int i = 0; i < cstructs.length; i++) {
-            Class[] types = cstructs[i].getParameterTypes();
-            if (types.length == 1 && types[0].equals(Throwable.class)) {
-                found = true;
-                break;
-            }
-        }
-        if (!found)
-            throw new IllegalArgumentException(wrapper + " does not have a single-arg constructor that takes a Throwable");
-    }
-
-    public CodeEmitter begin_method(int access, final Signature sig, final Type[] exceptions) {
-        CodeEmitter e = super.begin_method(access, sig, exceptions);
-        if (TypeUtils.isAbstract(access) || sig.equals(Constants.SIG_STATIC)) {
-            return e;
-        }
-        return new CodeEmitter(e) {
-            private Block handler;
-            /* init */ {
-                handler = begin_block();
-            }
-            public void visitMaxs(int maxStack, int maxLocals) {
-                handler.end();
-                EmitUtils.wrap_undeclared_throwable(this, handler, exceptions, wrapper);
-                super.visitMaxs(maxStack, maxLocals);
-            }
-        };
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/util/ParallelSorter.java b/cglib-and-asm/src/org/mockito/cglib/util/ParallelSorter.java
deleted file mode 100644
index 86ee703..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/util/ParallelSorter.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.util;
-
-import java.lang.reflect.*;
-import java.util.Comparator;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.cglib.core.*;
-
-/**
- * For the efficient sorting of multiple arrays in parallel.
- * <p>
- * Given two arrays of equal length and varying types, the standard
- * technique for sorting them in parallel is to create a new temporary
- * object for each row, store the objects in a temporary array, sort the
- * array using a custom comparator, and the extract the original values
- * back into their respective arrays. This is wasteful in both time and
- * memory.
- * <p>
- * This class generates bytecode customized to the particular set of
- * arrays you need to sort, in such a way that both arrays are sorted
- * in-place, simultaneously.
- * <p>
- * Two sorting algorithms are provided.
- * Quicksort is best when you only need to sort by a single column, as
- * it requires very few comparisons and swaps. Mergesort is best used
- * when sorting multiple columns, as it is a "stable" sort--that is, it
- * does not affect the relative order of equal objects from previous sorts.
- * <p>
- * The mergesort algorithm here is an "in-place" variant, which while
- * slower, does not require a temporary array.
- *
- * @author Chris Nokleberg
- */
-abstract public class ParallelSorter extends SorterTemplate {
-    protected Object[] a;
-    private Comparer comparer;
-    
-    protected ParallelSorter() {
-    }
-
-    abstract public ParallelSorter newInstance(Object[] arrays);
-
-    /**
-     * Create a new ParallelSorter object for a set of arrays. You may
-     * sort the arrays multiple times via the same ParallelSorter object.
-     * @param arrays An array of arrays to sort. The arrays may be a mix
-     * of primitive and non-primitive types, but should all be the same
-     * length.
-     * @param loader ClassLoader for generated class, uses "current" if null
-     */
-    public static ParallelSorter create(Object[] arrays) {
-        Generator gen = new Generator();
-        gen.setArrays(arrays);
-        return gen.create();
-    }
-
-    private int len() {
-        return ((Object[])a[0]).length;
-    }
-
-    /**
-     * Sort the arrays using the quicksort algorithm.
-     * @param index array (column) to sort by
-     */
-    public void quickSort(int index) {
-        quickSort(index, 0, len(), null);
-    }
-
-    /**
-     * Sort the arrays using the quicksort algorithm.
-     * @param index array (column) to sort by
-     * @param lo starting array index (row), inclusive
-     * @param hi ending array index (row), exclusive
-     */
-    public void quickSort(int index, int lo, int hi) {
-        quickSort(index, lo, hi, null);
-    }
-
-    /**
-     * Sort the arrays using the quicksort algorithm.
-     * @param index array (column) to sort by
-     * @param cmp Comparator to use if the specified column is non-primitive
-     */
-    public void quickSort(int index, Comparator cmp) {
-        quickSort(index, 0, len(), cmp);
-    }
-
-    /**
-     * Sort the arrays using the quicksort algorithm.
-     * @param index array (column) to sort by
-     * @param lo starting array index (row), inclusive
-     * @param hi ending array index (row), exclusive
-     * @param cmp Comparator to use if the specified column is non-primitive
-     */
-    public void quickSort(int index, int lo, int hi, Comparator cmp) {
-        chooseComparer(index, cmp);
-        super.quickSort(lo, hi - 1);
-    }
-
-    /**
-     * @param index array (column) to sort by
-     */
-    public void mergeSort(int index) {
-        mergeSort(index, 0, len(), null);
-    }
-
-    /**
-     * Sort the arrays using an in-place merge sort.
-     * @param index array (column) to sort by
-     * @param lo starting array index (row), inclusive
-     * @param hi ending array index (row), exclusive
-     */
-    public void mergeSort(int index, int lo, int hi) {
-        mergeSort(index, lo, hi, null);
-    }
-
-    /**
-     * Sort the arrays using an in-place merge sort.
-     * @param index array (column) to sort by
-     * @param lo starting array index (row), inclusive
-     * @param hi ending array index (row), exclusive
-     */
-    public void mergeSort(int index, Comparator cmp) {
-        mergeSort(index, 0, len(), cmp);
-    }
-
-    /**
-     * Sort the arrays using an in-place merge sort.
-     * @param index array (column) to sort by
-     * @param lo starting array index (row), inclusive
-     * @param hi ending array index (row), exclusive
-     * @param cmp Comparator to use if the specified column is non-primitive
-     */
-    public void mergeSort(int index, int lo, int hi, Comparator cmp) {
-        chooseComparer(index, cmp);
-        super.mergeSort(lo, hi - 1);
-    }
-    
-    private void chooseComparer(int index, Comparator cmp) {
-        Object array = a[index];
-        Class type = array.getClass().getComponentType();
-        if (type.equals(Integer.TYPE)) {
-            comparer = new IntComparer((int[])array);
-        } else if (type.equals(Long.TYPE)) {
-            comparer = new LongComparer((long[])array);
-        } else if (type.equals(Double.TYPE)) {
-            comparer = new DoubleComparer((double[])array);
-        } else if (type.equals(Float.TYPE)) {
-            comparer = new FloatComparer((float[])array);
-        } else if (type.equals(Short.TYPE)) {
-            comparer = new ShortComparer((short[])array);
-        } else if (type.equals(Byte.TYPE)) {
-            comparer = new ByteComparer((byte[])array);
-        } else if (cmp != null) {
-            comparer = new ComparatorComparer((Object[])array, cmp);
-        } else {
-            comparer = new ObjectComparer((Object[])array);
-        } 
-    }
-
-    protected int compare(int i, int j) {
-        return comparer.compare(i, j);
-    }
-
-    interface Comparer {
-        int compare(int i, int j);
-    }
-
-    static class ComparatorComparer implements Comparer {
-        private Object[] a;
-        private Comparator cmp;
-
-        public ComparatorComparer(Object[] a, Comparator cmp) {
-            this.a = a;
-            this.cmp = cmp;
-        }
-
-        public int compare(int i, int j) {
-            return cmp.compare(a[i], a[j]);
-        }
-    }
-    
-    static class ObjectComparer implements Comparer {
-        private Object[] a;
-        public ObjectComparer(Object[] a) { this.a = a; }
-        public int compare(int i, int j) {
-            return ((Comparable)a[i]).compareTo(a[j]);
-        }
-    }
-
-    static class IntComparer implements Comparer {
-        private int[] a;
-        public IntComparer(int[] a) { this.a = a; }
-        public int compare(int i, int j) { return a[i] - a[j]; }
-    }
-
-    static class LongComparer implements Comparer {
-        private long[] a;
-        public LongComparer(long[] a) { this.a = a; }
-        public int compare(int i, int j) {
-            long vi = a[i];
-            long vj = a[j];
-            return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
-        }
-    }
-
-    static class FloatComparer implements Comparer {
-        private float[] a;
-        public FloatComparer(float[] a) { this.a = a; }
-        public int compare(int i, int j) {
-            float vi = a[i];
-            float vj = a[j];
-            return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
-        }
-    }
-    
-    static class DoubleComparer implements Comparer {
-        private double[] a;
-        public DoubleComparer(double[] a) { this.a = a; }
-        public int compare(int i, int j) {
-            double vi = a[i];
-            double vj = a[j];
-            return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
-        }
-    }
-
-    static class ShortComparer implements Comparer {
-        private short[] a;
-        public ShortComparer(short[] a) { this.a = a; }
-        public int compare(int i, int j) { return a[i] - a[j]; }
-    }
-
-    static class ByteComparer implements Comparer {
-        private byte[] a;
-        public ByteComparer(byte[] a) { this.a = a; }
-        public int compare(int i, int j) { return a[i] - a[j]; }
-    }
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(ParallelSorter.class.getName());
-
-        private Object[] arrays;
-
-        public Generator() {
-            super(SOURCE);
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return null; // TODO
-        }
-
-        public void setArrays(Object[] arrays) {
-            this.arrays = arrays;
-        }
-
-        public ParallelSorter create() {
-            return (ParallelSorter)super.create(ClassesKey.create(arrays));
-        }
-
-        public void generateClass(ClassVisitor v) throws Exception {
-            if (arrays.length == 0) {
-                throw new IllegalArgumentException("No arrays specified to sort");
-            }
-            for (int i = 0; i < arrays.length; i++) {
-                if (!arrays[i].getClass().isArray()) {
-                    throw new IllegalArgumentException(arrays[i].getClass() + " is not an array");
-                }
-            }
-            new ParallelSorterEmitter(v, getClassName(), arrays);
-        }
-        
-        protected Object firstInstance(Class type) {
-            return ((ParallelSorter)ReflectUtils.newInstance(type)).newInstance(arrays);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return ((ParallelSorter)instance).newInstance(arrays);
-        }
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/util/ParallelSorterEmitter.java b/cglib-and-asm/src/org/mockito/cglib/util/ParallelSorterEmitter.java
deleted file mode 100644
index 16bbd40..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/util/ParallelSorterEmitter.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.util;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-class ParallelSorterEmitter extends ClassEmitter {
-    private static final Type PARALLEL_SORTER =
-      TypeUtils.parseType("org.mockito.cglib.util.ParallelSorter");
-    private static final Signature CSTRUCT_OBJECT_ARRAY =
-      TypeUtils.parseConstructor("Object[]");
-    private static final Signature NEW_INSTANCE =
-      new Signature("newInstance", PARALLEL_SORTER, new Type[]{ Constants.TYPE_OBJECT_ARRAY });
-    private static final Signature SWAP =
-      TypeUtils.parseSignature("void swap(int, int)");
-
-    public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) {
-        super(v);
-        begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE);
-        EmitUtils.null_constructor(this);
-        EmitUtils.factory_method(this, NEW_INSTANCE);
-        generateConstructor(arrays);
-        generateSwap(arrays);
-        end_class();
-    }
-
-    private String getFieldName(int index) {
-        return "FIELD_" + index;
-    }
-
-    private void generateConstructor(Object[] arrays) {
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null);
-        e.load_this();
-        e.super_invoke_constructor();
-        e.load_this();
-        e.load_arg(0);
-        e.super_putfield("a", Constants.TYPE_OBJECT_ARRAY);
-        for (int i = 0; i < arrays.length; i++) {
-            Type type = Type.getType(arrays[i].getClass());
-            declare_field(Constants.ACC_PRIVATE, getFieldName(i), type, null);
-            e.load_this();
-            e.load_arg(0);
-            e.push(i);
-            e.aaload();
-            e.checkcast(type);
-            e.putfield(getFieldName(i));
-        }
-        e.return_value();
-        e.end_method();
-    }
-
-    private void generateSwap(final Object[] arrays) {
-        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SWAP, null);
-        for (int i = 0; i < arrays.length; i++) {
-            Type type = Type.getType(arrays[i].getClass());
-            Type component = TypeUtils.getComponentType(type);
-            Local T = e.make_local(type);
-
-            e.load_this();
-            e.getfield(getFieldName(i));
-            e.store_local(T);
-
-            e.load_local(T);
-            e.load_arg(0);
-
-            e.load_local(T);
-            e.load_arg(1);
-            e.array_load(component);
-                
-            e.load_local(T);
-            e.load_arg(1);
-
-            e.load_local(T);
-            e.load_arg(0);
-            e.array_load(component);
-
-            e.array_store(component);
-            e.array_store(component);
-        }
-        e.return_value();
-        e.end_method();
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/util/SorterTemplate.java b/cglib-and-asm/src/org/mockito/cglib/util/SorterTemplate.java
deleted file mode 100644
index 00bcf3b..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/util/SorterTemplate.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.util;
-
-import java.util.*;
-
-abstract class SorterTemplate {
-    private static final int MERGESORT_THRESHOLD = 12;
-    private static final int QUICKSORT_THRESHOLD = 7;
-
-    abstract protected void swap(int i, int j);
-    abstract protected int compare(int i, int j);
-
-    protected void quickSort(int lo, int hi) {
-        quickSortHelper(lo, hi);
-        insertionSort(lo, hi);
-    }
-
-    private void quickSortHelper(int lo, int hi) {
-        for (;;) {
-            int diff = hi - lo;
-            if (diff <= QUICKSORT_THRESHOLD) {
-                break;
-            }
-            int i = (hi + lo) / 2;
-            if (compare(lo, i) > 0) {
-                swap(lo, i);
-            }
-            if (compare(lo, hi) > 0) {
-                swap(lo, hi);
-            }
-            if (compare(i, hi) > 0) {
-                swap(i, hi);
-            }
-            int j = hi - 1;
-            swap(i, j);
-            i = lo;
-            int v = j;
-            for (;;) {
-                while (compare(++i, v) < 0) {
-                    /* nothing */;
-                }
-                while (compare(--j, v) > 0) {
-                    /* nothing */;
-                }
-                if (j < i) {
-                    break;
-                }
-                swap(i, j);
-            }
-            swap(i, hi - 1);
-            if (j - lo <= hi - i + 1) {
-                quickSortHelper(lo, j);
-                lo = i + 1;
-            } else {
-                quickSortHelper(i + 1, hi);
-                hi = j;
-            }
-        }
-    }
-    
-    private void insertionSort(int lo, int hi) {
-        for (int i = lo + 1 ; i <= hi; i++) {
-            for (int j = i; j > lo; j--) {
-                if (compare(j - 1, j) > 0) {
-                    swap(j - 1, j);
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-    protected void mergeSort(int lo, int hi) {
-        int diff = hi - lo;
-        if (diff <= MERGESORT_THRESHOLD) {
-            insertionSort(lo, hi);
-            return;
-        }
-        int mid = lo + diff / 2;
-        mergeSort(lo, mid);
-        mergeSort(mid, hi);
-        merge(lo, mid, hi, mid - lo, hi - mid);
-    }
-
-    private void merge(int lo, int pivot, int hi, int len1, int len2) {
-        if (len1 == 0 || len2 == 0) {
-            return;
-        }
-        if (len1 + len2 == 2) {
-            if (compare(pivot, lo) < 0) {
-                swap(pivot, lo);
-            }
-            return;
-        }
-        int first_cut, second_cut;
-        int len11, len22;
-        if (len1 > len2) {
-            len11 = len1 / 2;
-            first_cut = lo + len11;
-            second_cut = lower(pivot, hi, first_cut);
-            len22 = second_cut - pivot;
-        } else {
-            len22 = len2 / 2;
-            second_cut = pivot + len22;
-            first_cut = upper(lo, pivot, second_cut);
-            len11 = first_cut - lo;
-        }
-        rotate(first_cut, pivot, second_cut);
-        int new_mid = first_cut + len22;
-        merge(lo, first_cut, new_mid, len11, len22);
-        merge(new_mid, second_cut, hi, len1 - len11, len2 - len22);
-    }
-
-    private void rotate(int lo, int mid, int hi) {
-        int lot = lo;
-        int hit = mid - 1;
-        while (lot < hit) {
-            swap(lot++, hit--);
-        }
-        lot = mid; hit = hi - 1;
-        while (lot < hit) {
-            swap(lot++, hit--);
-        }
-        lot = lo; hit = hi - 1;
-        while (lot < hit) {
-            swap(lot++, hit--);
-        }
-    }
-
-    private int lower(int lo, int hi, int val) {
-        int len = hi - lo;
-        while (len > 0) {
-            int half = len / 2;
-            int mid= lo + half;
-            if (compare(mid, val) < 0) {
-                lo = mid + 1;
-                len = len - half -1;
-            } else {
-                len = half;
-            }
-        }
-        return lo;
-    }
-
-    private int upper(int lo, int hi, int val) {
-        int len = hi - lo;
-        while (len > 0) {
-            int half = len / 2;
-            int mid = lo + half;
-            if (compare(val, mid) < 0) {
-                len = half;
-            } else {
-                lo = mid + 1;
-                len = len - half -1;
-            }
-        }
-        return lo;
-    }
-}
diff --git a/cglib-and-asm/src/org/mockito/cglib/util/StringSwitcher.java b/cglib-and-asm/src/org/mockito/cglib/util/StringSwitcher.java
deleted file mode 100644
index a607008..0000000
--- a/cglib-and-asm/src/org/mockito/cglib/util/StringSwitcher.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2003 The Apache Software Foundation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.mockito.cglib.util;
-
-import java.util.*;
-
-import org.mockito.asm.ClassVisitor;
-import org.mockito.asm.Label;
-import org.mockito.asm.Type;
-import org.mockito.cglib.core.*;
-
-/**
- * This class implements a simple String->int mapping for a fixed set of keys.
- */
-abstract public class StringSwitcher {
-    private static final Type STRING_SWITCHER =
-      TypeUtils.parseType("org.mockito.cglib.util.StringSwitcher");
-    private static final Signature INT_VALUE =
-      TypeUtils.parseSignature("int intValue(String)");
-    private static final StringSwitcherKey KEY_FACTORY =
-      (StringSwitcherKey)KeyFactory.create(StringSwitcherKey.class);
-
-    interface StringSwitcherKey {
-        public Object newInstance(String[] strings, int[] ints, boolean fixedInput);
-    }
-
-    /**
-     * Helper method to create a StringSwitcher.
-     * For finer control over the generated instance, use a new instance of StringSwitcher.Generator
-     * instead of this static method.
-     * @param strings the array of String keys; must be the same length as the value array
-     * @param ints the array of integer results; must be the same length as the key array
-     * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true,
-     * the result will be undefined, and the resulting code will be faster
-     */
-    public static StringSwitcher create(String[] strings, int[] ints, boolean fixedInput) {
-        Generator gen = new Generator();
-        gen.setStrings(strings);
-        gen.setInts(ints);
-        gen.setFixedInput(fixedInput);
-        return gen.create();
-    }
-
-    protected StringSwitcher() {
-    }
-
-    /**
-     * Return the integer associated with the given key.
-     * @param s the key
-     * @return the associated integer value, or <code>-1</code> if the key is unknown (unless
-     * <code>fixedInput</code> was specified when this <code>StringSwitcher</code> was created,
-     * in which case the return value for an unknown key is undefined)
-     */
-    abstract public int intValue(String s);
-
-    public static class Generator extends AbstractClassGenerator {
-        private static final Source SOURCE = new Source(StringSwitcher.class.getName());
-
-        private String[] strings;
-        private int[] ints;
-        private boolean fixedInput;
-        
-        public Generator() {
-            super(SOURCE);
-        }
-
-        /**
-         * Set the array of recognized Strings.
-         * @param strings the array of String keys; must be the same length as the value array
-         * @see #setInts
-         */
-        public void setStrings(String[] strings) {
-            this.strings = strings;
-        }
-
-        /**
-         * Set the array of integer results.
-         * @param ints the array of integer results; must be the same length as the key array
-         * @see #setStrings
-         */
-        public void setInts(int[] ints) {
-            this.ints = ints;
-        }
-
-        /**
-         * Configure how unknown String keys will be handled.
-         * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true,
-         * the result will be undefined, and the resulting code will be faster
-         */
-        public void setFixedInput(boolean fixedInput) {
-            this.fixedInput = fixedInput;
-        }
-
-        protected ClassLoader getDefaultClassLoader() {
-            return getClass().getClassLoader();
-        }
-
-        /**
-         * Generate the <code>StringSwitcher</code>.
-         */
-        public StringSwitcher create() {
-            setNamePrefix(StringSwitcher.class.getName());
-            Object key = KEY_FACTORY.newInstance(strings, ints, fixedInput);
-            return (StringSwitcher)super.create(key);
-        }
-
-        public void generateClass(ClassVisitor v) throws Exception {
-            ClassEmitter ce = new ClassEmitter(v);
-            ce.begin_class(Constants.V1_2,
-                           Constants.ACC_PUBLIC,
-                           getClassName(),
-                           STRING_SWITCHER,
-                           null,
-                           Constants.SOURCE_FILE);
-            EmitUtils.null_constructor(ce);
-            final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, INT_VALUE, null);
-            e.load_arg(0);
-            final List stringList = Arrays.asList(strings);
-            int style = fixedInput ? Constants.SWITCH_STYLE_HASHONLY : Constants.SWITCH_STYLE_HASH;
-            EmitUtils.string_switch(e, strings, style, new ObjectSwitchCallback() {
-                public void processCase(Object key, Label end) {
-                    e.push(ints[stringList.indexOf(key)]);
-                    e.return_value();
-                }
-                public void processDefault() {
-                    e.push(-1);
-                    e.return_value();
-                }
-            });
-            e.end_method();
-            ce.end_class();
-        }
-
-        protected Object firstInstance(Class type) {
-            return (StringSwitcher)ReflectUtils.newInstance(type);
-        }
-
-        protected Object nextInstance(Object instance) {
-            return instance;
-        }
-    }
-}
diff --git a/lib/byte-buddy-1.6.9-sources.jar b/lib/byte-buddy-1.6.9-sources.jar
new file mode 100644
index 0000000..50be6a1
--- /dev/null
+++ b/lib/byte-buddy-1.6.9-sources.jar
Binary files differ
diff --git a/lib/byte-buddy-1.6.9.jar b/lib/byte-buddy-1.6.9.jar
new file mode 100644
index 0000000..99062ce
--- /dev/null
+++ b/lib/byte-buddy-1.6.9.jar
Binary files differ
diff --git a/lib/byte-buddy-1.6.9.jar.txt b/lib/byte-buddy-1.6.9.jar.txt
new file mode 100644
index 0000000..e06d208
--- /dev/null
+++ b/lib/byte-buddy-1.6.9.jar.txt
@@ -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/lib/byte-buddy-agent-1.6.9-sources.jar b/lib/byte-buddy-agent-1.6.9-sources.jar
new file mode 100644
index 0000000..5d65166
--- /dev/null
+++ b/lib/byte-buddy-agent-1.6.9-sources.jar
Binary files differ
diff --git a/lib/byte-buddy-agent-1.6.9.jar b/lib/byte-buddy-agent-1.6.9.jar
new file mode 100644
index 0000000..036c779
--- /dev/null
+++ b/lib/byte-buddy-agent-1.6.9.jar
Binary files differ
diff --git a/lib/byte-buddy-agent-1.6.9.jar.txt b/lib/byte-buddy-agent-1.6.9.jar.txt
new file mode 100644
index 0000000..e06d208
--- /dev/null
+++ b/lib/byte-buddy-agent-1.6.9.jar.txt
@@ -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/src/main/java/org/mockito/AdditionalAnswers.java b/src/main/java/org/mockito/AdditionalAnswers.java
index b184928..287e4b1 100644
--- a/src/main/java/org/mockito/AdditionalAnswers.java
+++ b/src/main/java/org/mockito/AdditionalAnswers.java
@@ -4,39 +4,76 @@
  */
 package org.mockito;
 
+import java.util.Collection;
 import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
 import org.mockito.internal.stubbing.answers.ReturnsElementsOf;
 import org.mockito.internal.stubbing.defaultanswers.ForwardsInvocations;
 import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Answer1;
+import org.mockito.stubbing.Answer2;
+import org.mockito.stubbing.Answer3;
+import org.mockito.stubbing.Answer4;
+import org.mockito.stubbing.Answer5;
+import org.mockito.stubbing.VoidAnswer1;
+import org.mockito.stubbing.VoidAnswer2;
+import org.mockito.stubbing.VoidAnswer3;
+import org.mockito.stubbing.VoidAnswer4;
+import org.mockito.stubbing.VoidAnswer5;
 
-import java.util.Collection;
+import static org.mockito.internal.stubbing.answers.AnswerFunctionalInterfaces.toAnswer;
 
 /**
- * Additional answers provides factory methods for less common answers.
+ * Additional answers provides factory methods for answers.
  *
- * <p>Currently offer answers that can return the parameter of an invocation at a certain position.
+ * <p>Currently offer answers that can return the parameter of an invocation at a certain position,
+ * along with answers that draw on a strongly typed interface to provide a neater way to write custom answers
+ * that either return a value or are void (see answer interfaces in {@link org.mockito.stubbing}).
  *
  * <p>See factory methods for more information : {@link #returnsFirstArg}, {@link #returnsSecondArg},
- * {@link #returnsLastArg} and {@link #returnsArgAt}
+ * {@link #returnsLastArg}, {@link #returnsArgAt}, {@link #answer} and {@link #answerVoid}
  *
  * @since 1.9.5
  */
 @SuppressWarnings("unchecked")
 public class AdditionalAnswers {
-    private static final ReturnsArgumentAt RETURNS_FIRST_ARGUMENT = new ReturnsArgumentAt(0);
-    private static final ReturnsArgumentAt RETURNS_SECOND_ARGUMENT = new ReturnsArgumentAt(1);
-    private static final ReturnsArgumentAt RETURNS_LAST_ARGUMENT = new ReturnsArgumentAt(-1);
-
     /**
      * Returns the first parameter of an invocation.
      *
      * <p>
      *     This additional answer could be used at stub time using the
      *     <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(carKeyFob.authenticate(carKey)).will(returnsFirstArg());
+     * doAnswer(returnsFirstArg()).when(carKeyFob).authenticate(carKey);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(carKeyFob.authenticate(carKey)).will(returnsFirstArg());
-     * doAnswer(returnsFirstArg()).when(carKeyFob).authenticate(carKey)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream... dreams);
+     * }
+     *
+     * // returns dream1
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsFirstArg());
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the first argument is a vararg in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams (happens to be a 4 elements array)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsFirstArg());
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @return Answer that will return the first argument of the invocation.
@@ -44,7 +81,7 @@
      * @since 1.9.5
      */
     public static <T> Answer<T> returnsFirstArg() {
-        return (Answer<T>) RETURNS_FIRST_ARGUMENT;
+        return (Answer<T>) new ReturnsArgumentAt(0);
     }
 
     /**
@@ -53,10 +90,38 @@
      * <p>
      *     This additional answer could be used at stub time using the
      *     <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(trader.apply(leesFormula, onCreditDefaultSwap)).will(returnsSecondArg());
+     * doAnswer(returnsSecondArg()).when(trader).apply(leesFormula, onCreditDefaultSwap);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(trader.apply(leesFormula, onCreditDefaultSwap)).will(returnsSecondArg());
-     * doAnswer(returnsSecondArg()).when(trader).apply(leesFormula, onCreditDefaultSwap)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns dream2
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsSecondArg());
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the second argument is a vararg in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream dream1, Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams (happens to be a 3 elements array)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsSecondArg());
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @return Answer that will return the second argument of the invocation.
@@ -64,7 +129,7 @@
      * @since 1.9.5
      */
     public static <T> Answer<T> returnsSecondArg() {
-        return (Answer<T>) RETURNS_SECOND_ARGUMENT;
+        return (Answer<T>) new ReturnsArgumentAt(1);
     }
 
     /**
@@ -73,10 +138,38 @@
      * <p>
      *     This additional answer could be used at stub time using the
      *     <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+     * doAnswer(returnsLastArg()).when(person).remember(dream1, dream2, dream3, dream4);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
-     * doAnswer(returnsLastArg()).when(person).remember(dream1, dream2, dream3, dream4)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns dream4
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the given {@code position} targets the vararg index in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream dream1, Dream dream2, Dream dream3, Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams (happens to be a single element array)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @return Answer that will return the last argument of the invocation.
@@ -84,7 +177,7 @@
      * @since 1.9.5
      */
     public static <T> Answer<T> returnsLastArg() {
-        return (Answer<T>) RETURNS_LAST_ARGUMENT;
+        return (Answer<T>) new ReturnsArgumentAt(ReturnsArgumentAt.LAST_ARGUMENT);
     }
 
     /**
@@ -93,10 +186,38 @@
      * <p>
      * This additional answer could be used at stub time using the
      * <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(3));
+     * doAnswer(returnsArgAt(3)).when(person).remember(dream1, dream2, dream3, dream4);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(3));
-     * doAnswer(returnsArgAt(3)).when(person).remember(dream1, dream2, dream3, dream4)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns dream 3
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(2));
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the given {@code position} targets the vararg index in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams array (contains dream2, dream,3, dream4)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(1));
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @param position index of the argument from the list of arguments.
@@ -119,8 +240,7 @@
      *     <li>Already custom proxied object</li>
      *     <li>Special objects with a finalize method, i.e. to avoid executing it 2 times</li>
      * </ul>
-     * For more details including the use cases reported by users take a look at
-     * <a link="http://code.google.com/p/mockito/issues/detail?id=145">issue 145</a>.
+     *
      * <p>
      * The difference with the regular spy:
      * <ul>
@@ -195,4 +315,160 @@
     public static <T> Answer<T> returnsElementsOf(Collection<?> elements) {
         return (Answer<T>) new ReturnsElementsOf(elements);
     }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - which is expected to return something
+     * @param <T> return type
+     * @param <A> input parameter type 1
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <T, A> Answer<T> answer(Answer1<T, A> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - a void method
+     * @param <A> input parameter type 1
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <A> Answer<Void> answerVoid(VoidAnswer1<A> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - which is expected to return something
+     * @param <T> return type
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <T, A, B> Answer<T> answer(Answer2<T, A, B> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - a void method
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <A, B> Answer<Void> answerVoid(VoidAnswer2<A, B> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - which is expected to return something
+     * @param <T> return type
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @param <C> input parameter type 3
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <T, A, B, C> Answer<T> answer(Answer3<T, A, B, C> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - a void method
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @param <C> input parameter type 3
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <A, B, C> Answer<Void> answerVoid(VoidAnswer3<A, B, C> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - which is expected to return something
+     * @param <T> return type
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @param <C> input parameter type 3
+     * @param <D> input parameter type 4
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <T, A, B, C, D> Answer<T> answer(Answer4<T, A, B, C, D> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - a void method
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @param <C> input parameter type 3
+     * @param <D> input parameter type 4
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <A, B, C, D> Answer<Void> answerVoid(VoidAnswer4<A, B, C, D> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     * @param answer interface to the answer - which is expected to return something
+     * @param <T> return type
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @param <C> input parameter type 3
+     * @param <D> input parameter type 4
+     * @param <E> input parameter type 5
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <T, A, B, C, D, E> Answer<T> answer(Answer5<T, A, B, C, D, E> answer) {
+        return toAnswer(answer);
+    }
+
+    /**
+     * Creates an answer from a functional interface - allows for a strongly typed answer to be created
+     * ideally in Java 8
+     *
+     * @param answer interface to the answer - a void method
+     * @param <A> input parameter type 1
+     * @param <B> input parameter type 2
+     * @param <C> input parameter type 3
+     * @param <D> input parameter type 4
+     * @param <E> input parameter type 5
+     * @return the answer object to use
+     * @since 2.1.0
+     */
+    @Incubating
+    public static <A, B, C, D, E> Answer<Void> answerVoid(VoidAnswer5<A, B, C, D, E> answer) {
+        return toAnswer(answer);
+    }
 }
diff --git a/src/main/java/org/mockito/AdditionalMatchers.java b/src/main/java/org/mockito/AdditionalMatchers.java
index f5b7606..8f6d11c 100644
--- a/src/main/java/org/mockito/AdditionalMatchers.java
+++ b/src/main/java/org/mockito/AdditionalMatchers.java
@@ -5,6 +5,8 @@
 
 package org.mockito;
 
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
 import org.mockito.internal.matchers.ArrayEquals;
 import org.mockito.internal.matchers.CompareEqual;
 import org.mockito.internal.matchers.EqualsWithDelta;
@@ -13,398 +15,422 @@
 import org.mockito.internal.matchers.GreaterThan;
 import org.mockito.internal.matchers.LessOrEqual;
 import org.mockito.internal.matchers.LessThan;
-import org.mockito.internal.progress.HandyReturnValues;
-import org.mockito.internal.progress.MockingProgress;
-import org.mockito.internal.progress.ThreadSafeMockingProgress;
 
 /**
  * See {@link Matchers} for general info about matchers.
  * <p>
- * AdditionalMatchers provides rarely used matchers, kept only for somewhat compatibility with EasyMock. 
+ * AdditionalMatchers provides rarely used matchers, kept only for somewhat compatibility with EasyMock.
  * Use additional matchers very judiciously because they may impact readability of a test.
  * It is recommended to use matchers from {@link Matchers} and keep stubbing and verification simple.
  * <p>
- * Example of using logical and(), not(), or() matchers: 
- *  
+ * Example of using logical and(), not(), or() matchers:
+ *
  * <pre class="code"><code class="java">
  *   //anything but not "ejb"
  *   mock.someMethod(not(eq("ejb")));
- *   
+ *
  *   //not "ejb" and not "michael jackson"
  *   mock.someMethod(and(not(eq("ejb")), not(eq("michael jackson"))));
- *   
+ *
  *   //1 or 10
  *   mock.someMethod(or(eq(1), eq(10)));
  * </code></pre>
- * 
+ *
  * Scroll down to see all methods - full list of matchers.
  */
+@SuppressWarnings("ALL")
 public class AdditionalMatchers {
-    
-    private static final MockingProgress MOCKING_PROGRESS = new ThreadSafeMockingProgress();
 
     /**
      * argument greater than or equal the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>null</code>.
      */
-    public static <T extends Comparable<T>> T geq(Comparable<T> value) {
-        return reportMatcher(new GreaterOrEqual<T>(value)).<T>returnNull();
+    public static <T extends Comparable<T>> T geq(T value) {
+        reportMatcher(new GreaterOrEqual<T>(value));
+        return null;
     }
 
     /**
      * byte argument greater than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static byte geq(byte value) {
-        return reportMatcher(new GreaterOrEqual<Byte>(value)).returnZero();
+        reportMatcher(new GreaterOrEqual<Byte>(value));
+        return 0;
     }
 
     /**
      * double argument greater than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static double geq(double value) {
-        return reportMatcher(new GreaterOrEqual<Double>(value)).returnZero();
+        reportMatcher(new GreaterOrEqual<Double>(value));
+        return 0;
     }
 
     /**
      * float argument greater than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static float geq(float value) {
-        return reportMatcher(new GreaterOrEqual<Float>(value)).returnZero();
+        reportMatcher(new GreaterOrEqual<Float>(value));
+        return 0;
     }
 
     /**
      * int argument greater than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static int geq(int value) {
-        return reportMatcher(new GreaterOrEqual<Integer>(value)).returnZero();
+        reportMatcher(new GreaterOrEqual<Integer>(value));
+        return 0;
     }
 
     /**
      * long argument greater than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static long geq(long value) {
-        return reportMatcher(new GreaterOrEqual<Long>(value)).returnZero();
+        reportMatcher(new GreaterOrEqual<Long>(value));
+        return 0;
     }
 
     /**
      * short argument greater than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static short geq(short value) {
-        return reportMatcher(new GreaterOrEqual<Short>(value)).returnZero();
+        reportMatcher(new GreaterOrEqual<Short>(value));
+        return 0;
     }
 
     /**
      * comparable argument less than or equal the given value details.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>null</code>.
      */
-    public static <T extends Comparable<T>> T leq(Comparable<T> value) {
-        return reportMatcher(new LessOrEqual<T>(value)).<T>returnNull();
+    public static <T extends Comparable<T>> T leq(T value) {
+        reportMatcher(new LessOrEqual<T>(value));
+        return null;
     }
 
     /**
      * byte argument less than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static byte leq(byte value) {
-        return reportMatcher(new LessOrEqual<Byte>(value)).returnZero();
+        reportMatcher(new LessOrEqual<Byte>(value));
+        return 0;
     }
 
     /**
      * double argument less than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static double leq(double value) {
-        return reportMatcher(new LessOrEqual<Double>(value)).returnZero();
+        reportMatcher(new LessOrEqual<Double>(value));
+        return 0;
     }
 
     /**
      * float argument less than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static float leq(float value) {
-        return reportMatcher(new LessOrEqual<Float>(value)).returnZero();
+        reportMatcher(new LessOrEqual<Float>(value));
+        return 0;
     }
 
     /**
      * int argument less than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static int leq(int value) {
-        return reportMatcher(new LessOrEqual<Integer>(value)).returnZero();
+        reportMatcher(new LessOrEqual<Integer>(value));
+        return 0;
     }
 
     /**
      * long argument less than or equal to the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static long leq(long value) {
-        return reportMatcher(new LessOrEqual<Long>(value)).returnZero();
+        reportMatcher(new LessOrEqual<Long>(value));
+        return 0;
     }
 
     /**
      * short argument less than or equal to the given value.
      * <p>
-     * See examples in javadoc for {@link AdditionalMatchers} class 
-     * 
+     * See examples in javadoc for {@link AdditionalMatchers} class
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static short leq(short value) {
-        return reportMatcher(new LessOrEqual<Short>(value)).returnZero();
+        reportMatcher(new LessOrEqual<Short>(value));
+        return 0;
     }
 
     /**
      * comparable argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>null</code>.
      */
-    public static <T extends Comparable<T>> T gt(Comparable<T> value) {
-        return reportMatcher(new GreaterThan<T>(value)).<T>returnNull();
+    public static <T extends Comparable<T>> T gt(T value) {
+        reportMatcher(new GreaterThan<T>(value));
+        return null;
     }
 
     /**
      * byte argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static byte gt(byte value) {
-        return reportMatcher(new GreaterThan<Byte>(value)).returnZero();
+        reportMatcher(new GreaterThan<Byte>(value));
+        return 0;
     }
 
     /**
      * double argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static double gt(double value) {
-        return reportMatcher(new GreaterThan<Double>(value)).returnZero();
+        reportMatcher(new GreaterThan<Double>(value));
+        return 0;
     }
 
     /**
      * float argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static float gt(float value) {
-        return reportMatcher(new GreaterThan<Float>(value)).returnZero();
+        reportMatcher(new GreaterThan<Float>(value));
+        return 0;
     }
 
     /**
      * int argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static int gt(int value) {
-        return reportMatcher(new GreaterThan<Integer>(value)).returnZero();
+        reportMatcher(new GreaterThan<Integer>(value));
+        return 0;
     }
 
     /**
      * long argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static long gt(long value) {
-        return reportMatcher(new GreaterThan<Long>(value)).returnZero();
+        reportMatcher(new GreaterThan<Long>(value));
+        return 0;
     }
 
     /**
      * short argument greater than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static short gt(short value) {
-        return reportMatcher(new GreaterThan<Short>(value)).returnZero();
+        reportMatcher(new GreaterThan<Short>(value));
+        return 0;
     }
 
     /**
      * comparable argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>null</code>.
      */
-    public static <T extends Comparable<T>> T lt(Comparable<T> value) {
-        return reportMatcher(new LessThan<T>(value)).<T>returnNull();
+    public static <T extends Comparable<T>> T lt(T value) {
+        reportMatcher(new LessThan<T>(value));
+        return null;
     }
 
     /**
      * byte argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static byte lt(byte value) {
-        return reportMatcher(new LessThan<Byte>(value)).returnZero();
+        reportMatcher(new LessThan<Byte>(value));
+        return 0;
     }
 
     /**
      * double argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static double lt(double value) {
-        return reportMatcher(new LessThan<Double>(value)).returnZero();
+        reportMatcher(new LessThan<Double>(value));
+        return 0;
     }
 
     /**
      * float argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static float lt(float value) {
-        return reportMatcher(new LessThan<Float>(value)).returnZero();
+        reportMatcher(new LessThan<Float>(value));
+        return 0;
     }
 
     /**
      * int argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static int lt(int value) {
-        return reportMatcher(new LessThan<Integer>(value)).returnZero();
+        reportMatcher(new LessThan<Integer>(value));
+        return 0;
     }
 
     /**
      * long argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static long lt(long value) {
-        return reportMatcher(new LessThan<Long>(value)).returnZero();
+        reportMatcher(new LessThan<Long>(value));
+        return 0;
     }
 
     /**
      * short argument less than the given value.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>0</code>.
      */
     public static short lt(short value) {
-        return reportMatcher(new LessThan<Short>(value)).returnZero();
+        reportMatcher(new LessThan<Short>(value));
+        return 0;
     }
 
     /**
@@ -412,25 +438,27 @@
      * compareTo method.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @return <code>null</code>.
      */
-    public static <T extends Comparable<T>> T cmpEq(Comparable<T> value) {
-        return reportMatcher(new CompareEqual<T>(value)).<T>returnNull();
+    public static <T extends Comparable<T>> T cmpEq(T value) {
+        reportMatcher(new CompareEqual<T>(value));
+        return null;
     }
 
     /**
      * String argument that contains a substring that matches the given regular
      * expression.
-     * 
+     *
      * @param regex
      *            the regular expression.
      * @return <code>null</code>.
      */
     public static String find(String regex) {
-        return reportMatcher(new Find(regex)).<String>returnNull();
+        reportMatcher(new Find(regex));
+        return null;
     }
 
     /**
@@ -438,7 +466,7 @@
      * have the same type, length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param <T>
      *            the type of the array, it is passed through to prevent casts.
      * @param value
@@ -446,7 +474,8 @@
      * @return <code>null</code>.
      */
     public static <T> T[] aryEq(T[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -454,13 +483,14 @@
      * have the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static short[] aryEq(short[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -468,13 +498,14 @@
      * the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static long[] aryEq(long[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -482,13 +513,14 @@
      * the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static int[] aryEq(int[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();       
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -496,13 +528,14 @@
      * have the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static float[] aryEq(float[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -510,13 +543,14 @@
      * have the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static double[] aryEq(double[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -524,13 +558,14 @@
      * the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static char[] aryEq(char[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -538,13 +573,14 @@
      * the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static byte[] aryEq(byte[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
@@ -552,20 +588,21 @@
      * have the same length, and each element has to be equal.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given array.
      * @return <code>null</code>.
      */
     public static boolean[] aryEq(boolean[] value) {
-        return reportMatcher(new ArrayEquals(value)).returnNull();
+        reportMatcher(new ArrayEquals(value));
+        return null;
     }
 
     /**
      * boolean argument that matches both given matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -573,14 +610,15 @@
      * @return <code>false</code>.
      */
     public static boolean and(boolean first, boolean second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnFalse();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return false;
     }
 
     /**
      * byte argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -588,14 +626,15 @@
      * @return <code>0</code>.
      */
     public static byte and(byte first, byte second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * char argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -603,14 +642,15 @@
      * @return <code>0</code>.
      */
     public static char and(char first, char second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnChar();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * double argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -618,14 +658,15 @@
      * @return <code>0</code>.
      */
     public static double and(double first, double second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * float argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -633,14 +674,15 @@
      * @return <code>0</code>.
      */
     public static float and(float first, float second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * int argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -648,14 +690,15 @@
      * @return <code>0</code>.
      */
     public static int and(int first, int second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * long argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -663,14 +706,15 @@
      * @return <code>0</code>.
      */
     public static long and(long first, long second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * short argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -678,14 +722,15 @@
      * @return <code>0</code>.
      */
     public static short and(short first, short second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return 0;
     }
 
     /**
      * Object argument that matches both given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param <T>
      *            the type of the object, it is passed through to prevent casts.
      * @param first
@@ -695,14 +740,15 @@
      * @return <code>null</code>.
      */
     public static <T> T and(T first, T second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportAnd().<T>returnNull();
+        mockingProgress().getArgumentMatcherStorage().reportAnd();
+        return null;
     }
 
     /**
      * boolean argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -710,14 +756,15 @@
      * @return <code>false</code>.
      */
     public static boolean or(boolean first, boolean second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnFalse();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return false;
     }
 
     /**
      * Object argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param <T>
      *            the type of the object, it is passed through to prevent casts.
      * @param first
@@ -727,14 +774,15 @@
      * @return <code>null</code>.
      */
     public static <T> T or(T first, T second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().<T>returnNull();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return null;
     }
 
     /**
      * short argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -742,14 +790,15 @@
      * @return <code>0</code>.
      */
     public static short or(short first, short second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * long argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -757,14 +806,15 @@
      * @return <code>0</code>.
      */
     public static long or(long first, long second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * int argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -772,14 +822,15 @@
      * @return <code>0</code>.
      */
     public static int or(int first, int second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * float argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -787,14 +838,15 @@
      * @return <code>0</code>.
      */
     public static float or(float first, float second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * double argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -802,14 +854,15 @@
      * @return <code>0</code>.
      */
     public static double or(double first, double second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * char argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -817,14 +870,15 @@
      * @return <code>0</code>.
      */
     public static char or(char first, char second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnChar();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * byte argument that matches any of the given argument matchers.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the first argument matcher.
      * @param second
@@ -832,14 +886,15 @@
      * @return <code>0</code>.
      */
     public static byte or(byte first, byte second) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportOr().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportOr();
+        return 0;
     }
 
     /**
      * Object argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param <T>
      *            the type of the object, it is passed through to prevent casts.
      * @param first
@@ -847,111 +902,120 @@
      * @return <code>null</code>.
      */
     public static <T> T not(T first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().<T>returnNull();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return null;
     }
 
     /**
      * short argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static short not(short first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
      * int argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static int not(int first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
      * long argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static long not(long first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
      * float argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static float not(float first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
      * double argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static double not(double first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
      * char argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static char not(char first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnChar();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
      * boolean argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>false</code>.
      */
     public static boolean not(boolean first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnFalse();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return false;
     }
 
     /**
      * byte argument that does not match the given argument matcher.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param first
      *            placeholder for the argument matcher.
      * @return <code>0</code>.
      */
     public static byte not(byte first) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportNot().returnZero();
+        mockingProgress().getArgumentMatcherStorage().reportNot();
+        return 0;
     }
 
     /**
@@ -959,7 +1023,7 @@
      * is less than the given delta details.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @param delta
@@ -967,15 +1031,16 @@
      * @return <code>0</code>.
      */
     public static double eq(double value, double delta) {
-        return reportMatcher(new EqualsWithDelta(value, delta)).returnZero();
+        reportMatcher(new EqualsWithDelta(value, delta));
+        return 0;
     }
-    
+
     /**
      * float argument that has an absolute difference to the given value that is
      * less than the given delta details.
      * <p>
      * See examples in javadoc for {@link AdditionalMatchers} class
-     * 
+     *
      * @param value
      *            the given value.
      * @param delta
@@ -983,10 +1048,11 @@
      * @return <code>0</code>.
      */
     public static float eq(float value, float delta) {
-        return reportMatcher(new EqualsWithDelta(value, delta)).returnZero();
+        reportMatcher(new EqualsWithDelta(value, delta));
+        return 0;
     }
-    
-    private static HandyReturnValues reportMatcher(ArgumentMatcher<?> matcher) {
-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportMatcher(matcher);
+
+    private static void reportMatcher(ArgumentMatcher<?> matcher) {
+        mockingProgress().getArgumentMatcherStorage().reportMatcher(matcher);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/Answers.java b/src/main/java/org/mockito/Answers.java
index 32d566f..1ba50d9 100644
--- a/src/main/java/org/mockito/Answers.java
+++ b/src/main/java/org/mockito/Answers.java
@@ -1,83 +1,102 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import org.mockito.internal.stubbing.answers.CallsRealMethods;

-import org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsMocks;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls;

-import org.mockito.stubbing.Answer;

-

-/**

- * Enumeration of pre-configured mock answers

- * <p>

- * You can use it to pass extra parameters to &#064;Mock annotation, see more info here: {@link Mock}

- * <p>

- * Example:

- * <pre class="code"><code class="java">

- *   &#064;Mock(answer = RETURNS_DEEP_STUBS) UserProvider userProvider;

- * </code></pre>

- * <b>This is not the full list</b> of Answers available in Mockito. Some interesting answers can be found in org.mockito.stubbing.answers package.

- */

-public enum Answers {

-

-    /**

-     * The default configured answer of every mock.

-     *

-     * <p>Please see the {@link org.mockito.Mockito#RETURNS_DEFAULTS} documentation for more details.</p>

-     *

-     * @see org.mockito.Mockito#RETURNS_DEFAULTS

-     */

-    RETURNS_DEFAULTS(new GloballyConfiguredAnswer()),

-

-    /**

-     * An answer that returns smart-nulls.

-     *

-     * <p>Please see the {@link org.mockito.Mockito#RETURNS_SMART_NULLS} documentation for more details.</p>

-     *

-     * @see org.mockito.Mockito#RETURNS_SMART_NULLS

-     */

-    RETURNS_SMART_NULLS(new ReturnsSmartNulls()),

-

-    /**

-     * An answer that returns <strong>mocks</strong> (not stubs).

-     *

-     * <p>Please see the {@link org.mockito.Mockito#RETURNS_MOCKS} documentation for more details.</p>

-     *

-     * @see org.mockito.Mockito#RETURNS_MOCKS

-     */

-    RETURNS_MOCKS(new ReturnsMocks()),

-

-

-    /**

-     * An answer that returns <strong>deep stubs</strong> (not mocks).

-     *

-     * <p>Please see the {@link org.mockito.Mockito#RETURNS_DEEP_STUBS} documentation for more details.</p>

-     *

-     * @see org.mockito.Mockito#RETURNS_DEEP_STUBS

-     */

-    RETURNS_DEEP_STUBS(new ReturnsDeepStubs()),

-

-    /**

-     * An answer that calls the real methods (used for partial mocks).

-     *

-     * <p>Please see the {@link org.mockito.Mockito#CALLS_REAL_METHODS} documentation for more details.</p>

-     *

-     * @see org.mockito.Mockito#CALLS_REAL_METHODS

-     */

-    CALLS_REAL_METHODS(new CallsRealMethods())

-    ;

-

-    private final Answer<Object> implementation;

-

-    private Answers(Answer<Object> implementation) {

-        this.implementation = implementation;

-    }

-

-    public Answer<Object> get() {

-        return implementation;

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.defaultanswers.TriesToReturnSelf;
+import org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsMocks;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Enumeration of pre-configured mock answers
+ * <p>
+ * You can use it to pass extra parameters to &#064;Mock annotation, see more info here: {@link Mock}
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ *   &#064;Mock(answer = RETURNS_DEEP_STUBS) UserProvider userProvider;
+ * </code></pre>
+ * <b>This is not the full list</b> of Answers available in Mockito. Some interesting answers can be found in org.mockito.stubbing.answers package.
+ */
+public enum Answers implements Answer<Object>{
+    /**
+     * The default configured answer of every mock.
+     *
+     * <p>Please see the {@link org.mockito.Mockito#RETURNS_DEFAULTS} documentation for more details.</p>
+     *
+     * @see org.mockito.Mockito#RETURNS_DEFAULTS
+     */
+    RETURNS_DEFAULTS(new GloballyConfiguredAnswer()),
+
+    /**
+     * An answer that returns smart-nulls.
+     *
+     * <p>Please see the {@link org.mockito.Mockito#RETURNS_SMART_NULLS} documentation for more details.</p>
+     *
+     * @see org.mockito.Mockito#RETURNS_SMART_NULLS
+     */
+    RETURNS_SMART_NULLS(new ReturnsSmartNulls()),
+
+    /**
+     * An answer that returns <strong>mocks</strong> (not stubs).
+     *
+     * <p>Please see the {@link org.mockito.Mockito#RETURNS_MOCKS} documentation for more details.</p>
+     *
+     * @see org.mockito.Mockito#RETURNS_MOCKS
+     */
+    RETURNS_MOCKS(new ReturnsMocks()),
+
+
+    /**
+     * An answer that returns <strong>deep stubs</strong> (not mocks).
+     *
+     * <p>Please see the {@link org.mockito.Mockito#RETURNS_DEEP_STUBS} documentation for more details.</p>
+     *
+     * @see org.mockito.Mockito#RETURNS_DEEP_STUBS
+     */
+    RETURNS_DEEP_STUBS(new ReturnsDeepStubs()),
+
+    /**
+     * An answer that calls the real methods (used for partial mocks).
+     *
+     * <p>Please see the {@link org.mockito.Mockito#CALLS_REAL_METHODS} documentation for more details.</p>
+     *
+     * @see org.mockito.Mockito#CALLS_REAL_METHODS
+     */
+    CALLS_REAL_METHODS(new CallsRealMethods()),
+
+    /**
+     * An answer that tries to return itself. This is useful for mocking {@code Builders}.
+     *
+     * <p>Please see the {@link org.mockito.Mockito#RETURNS_SELF} documentation for more details.</p>
+     *
+     * @see org.mockito.Mockito#RETURNS_SELF
+     */
+    RETURNS_SELF(new TriesToReturnSelf())
+    ;
+
+    private final Answer<Object> implementation;
+
+    Answers(Answer<Object> implementation) {
+        this.implementation = implementation;
+    }
+
+    /**
+     * @deprecated as of 2.1.0 Use the enum-constant directly, instead of this getter. This method will be removed in a future release<br>
+     * E.g. instead of <code>Answers.CALLS_REAL_METHODS.get()</code> use <code>Answers.CALLS_REAL_METHODS</code> .
+     */
+    @Deprecated
+    public Answer<Object> get() {
+        return this;
+    }
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        return implementation.answer(invocation);
+    }
+}
diff --git a/src/main/java/org/mockito/ArgumentCaptor.java b/src/main/java/org/mockito/ArgumentCaptor.java
index 0efe061..1104de9 100644
--- a/src/main/java/org/mockito/ArgumentCaptor.java
+++ b/src/main/java/org/mockito/ArgumentCaptor.java
@@ -1,172 +1,151 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import org.mockito.internal.matchers.CapturingMatcher;

-import org.mockito.internal.progress.HandyReturnValues;

-

-import java.util.List;

-

-/**

- * Use it to capture argument values for further assertions.

- *

- * <p>

- * Mockito verifies argument values in natural java style: by using an equals() method.

- * This is also the recommended way of matching arguments because it makes tests clean & simple.

- * In some situations though, it is helpful to assert on certain arguments after the actual verification.

- * For example:

- * <pre class="code"><code class="java">

- *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);

- *   verify(mock).doSomething(argument.capture());

- *   assertEquals("John", argument.getValue().getName());

- * </code></pre>

- *

- * Example of capturing varargs:

- * <pre class="code"><code class="java">

- *   //capturing varargs:

- *   ArgumentCaptor&lt;Person&gt; varArgs = ArgumentCaptor.forClass(Person.class);

- *   verify(mock).varArgMethod(varArgs.capture());

- *   List expected = asList(new Person("John"), new Person("Jane"));

- *   assertEquals(expected, varArgs.getAllValues());

- * </code></pre>

- *

- * <p>

- * <strong>Warning:</strong> it is recommended to use ArgumentCaptor with verification <strong>but not</strong> with stubbing.

- * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.

- * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.

- *

- * <p>

- * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).

- * Both techniques can be used for making sure certain arguments where passed to mocks. 

- * However, ArgumentCaptor may be a better fit if:

- * <ul>  

- * <li>custom argument matcher is not likely to be reused</li>

- * <li>you just need it to assert on argument values to complete verification</li>

- * </ul>

- * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.

- *

- * <p>

- * This utility class <strong>*don't do any type checks*</strong>, the generic signatures are only there to avoid casting

- * in your code. If you want specific types, then you should do that the captured values.

- * This behavior might change (type checks could be added) in a

- * future major release.

- * <p>

- * There is an <strong>annotation</strong> that you might find useful: &#64;{@link Captor}

- * <p>

- * See the full documentation on Mockito in javadoc for {@link Mockito} class.

- *

- * @see Captor

- * @since 1.8.0

- */

-public class ArgumentCaptor<T> {

-    

-    HandyReturnValues handyReturnValues = new HandyReturnValues();

-

-    private final CapturingMatcher<T> capturingMatcher = new CapturingMatcher<T>();

-    private final Class<T> clazz;

-

-    /**

-     * @deprecated

-     * 

-     * <b>Please use factory method {@link ArgumentCaptor#forClass(Class)} to create captors</b>

-     * <p>

-     * This is required to avoid NullPointerExceptions when autoUnboxing primitive types.

-     * See issue 99.

-     * <p>

-     * Example:

-     * <pre class="code"><code class="java">

-     *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);

-     *   verify(mock).doSomething(argument.capture());

-     *   assertEquals("John", argument.getValue().getName());

-     * </code></pre>

-     */

-    @Deprecated

-    public ArgumentCaptor() {

-        this.clazz = null;

-    }

-

-    ArgumentCaptor(Class<T> clazz) {

-        this.clazz = clazz;

-    }

-

-    /**

-     * Use it to capture the argument. This method <b>must be used inside of verification</b>.

-     * <p>

-     * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.

-     * This argument matcher stores the argument value so that you can use it later to perform assertions.  

-     * <p>

-     * See examples in javadoc for {@link ArgumentCaptor} class.

-     * 

-     * @return null or default values

-     */

-    public T capture() {

-        Mockito.argThat(capturingMatcher);

-        return handyReturnValues.returnFor(clazz);

-    }

-

-    /**

-     * Returns the captured value of the argument. When capturing varargs use {@link #getAllValues()}.

-     * <p>

-     * If verified method was called multiple times then this method it returns the latest captured value.

-     * <p>

-     * See examples in javadoc for {@link ArgumentCaptor} class.

-     * 

-     * @return captured argument value

-     */

-    public T getValue() {

-        return this.capturingMatcher.getLastValue();

-    }

-

-    /**

-     * Returns all captured values. Use it when capturing varargs or when the verified method was called multiple times.

-     * When varargs method was called multiple times, this method returns merged list of all values from all invocations.

-     * <p>

-     * Example: 

-     * <pre class="code"><code class="java">

-     *   mock.doSomething(new Person("John");

-     *   mock.doSomething(new Person("Jane");

-     *

-     *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);

-     *   verify(mock, times(2)).doSomething(peopleCaptor.capture());

-     *   

-     *   List&lt;Person&gt; capturedPeople = peopleCaptor.getAllValues();

-     *   assertEquals("John", capturedPeople.get(0).getName());

-     *   assertEquals("Jane", capturedPeople.get(1).getName());

-     * </pre>

-     *

-     * Example of capturing varargs:

-     * <pre class="code"><code class="java">

-     *   mock.countPeople(new Person("John"), new Person("Jane"); //vararg method

-     *

-     *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);

-     *

-     *   verify(mock).countPeople(peopleCaptor.capture());

-     *

-     *   List expected = asList(new Person("John"), new Person("Jane"));

-     *   assertEquals(expected, peopleCaptor.getAllValues());

-     * </code></pre>

-     * See more examples in javadoc for {@link ArgumentCaptor} class.

-     * 

-     * @return captured argument value

-     */

-    public List<T> getAllValues() {

-        return this.capturingMatcher.getAllValues();

-    }

-

-    /**

-     * Build a new <code>ArgumentCaptor</code>.

-     * <p>

-     * Note that an <code>ArgumentCaptor</code> <b>*don't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     *

-     * @param clazz Type matching the parameter to be captured.

-     * @param <T> Type of clazz

-     * @return A new ArgumentCaptor

-     */

-    public static <T> ArgumentCaptor<T> forClass(Class<T> clazz) {

-        return new ArgumentCaptor<T>(clazz);

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import static org.mockito.internal.util.Primitives.defaultValue;
+
+import java.util.List;
+
+import org.mockito.internal.matchers.CapturingMatcher;
+
+/**
+ * Use it to capture argument values for further assertions.
+ *
+ * <p>
+ * Mockito verifies argument values in natural java style: by using an equals() method.
+ * This is also the recommended way of matching arguments because it makes tests clean & simple.
+ * In some situations though, it is helpful to assert on certain arguments after the actual verification.
+ * For example:
+ * <pre class="code"><code class="java">
+ *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);
+ *   verify(mock).doSomething(argument.capture());
+ *   assertEquals("John", argument.getValue().getName());
+ * </code></pre>
+ *
+ * Example of capturing varargs:
+ * <pre class="code"><code class="java">
+ *   //capturing varargs:
+ *   ArgumentCaptor&lt;Person&gt; varArgs = ArgumentCaptor.forClass(Person.class);
+ *   verify(mock).varArgMethod(varArgs.capture());
+ *   List expected = asList(new Person("John"), new Person("Jane"));
+ *   assertEquals(expected, varArgs.getAllValues());
+ * </code></pre>
+ *
+ * <p>
+ * <strong>Warning:</strong> it is recommended to use ArgumentCaptor with verification <strong>but not</strong> with stubbing.
+ * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
+ * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
+ *
+ * <p>
+ * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
+ * Both techniques can be used for making sure certain arguments where passed to mocks.
+ * However, ArgumentCaptor may be a better fit if:
+ * <ul>
+ * <li>custom argument matcher is not likely to be reused</li>
+ * <li>you just need it to assert on argument values to complete verification</li>
+ * </ul>
+ * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.
+ *
+ * <p>
+ * This utility class <strong>*don't do any type checks*</strong>, the generic signatures are only there to avoid casting
+ * in your code.
+ * <p>
+ * There is an <strong>annotation</strong> that you might find useful: &#64;{@link Captor}
+ * <p>
+ * See the full documentation on Mockito in javadoc for {@link Mockito} class.
+ *
+ * @see Captor
+ * @since 1.8.0
+ */
+public class ArgumentCaptor<T> {
+
+
+    private final CapturingMatcher<T> capturingMatcher = new CapturingMatcher<T>();
+    private final Class<? extends T> clazz;
+
+    private ArgumentCaptor(Class<? extends T> clazz) {
+        this.clazz = clazz;
+    }
+
+    /**
+     * Use it to capture the argument. This method <b>must be used inside of verification</b>.
+     * <p>
+     * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
+     * This argument matcher stores the argument value so that you can use it later to perform assertions.
+     * <p>
+     * See examples in javadoc for {@link ArgumentCaptor} class.
+     *
+     * @return null or default values
+     */
+    public T capture() {
+        Mockito.argThat(capturingMatcher);
+        return defaultValue(clazz);
+    }
+
+    /**
+     * Returns the captured value of the argument. When capturing varargs use {@link #getAllValues()}.
+     * <p>
+     * If verified method was called multiple times then this method it returns the latest captured value.
+     * <p>
+     * See examples in javadoc for {@link ArgumentCaptor} class.
+     *
+     * @return captured argument value
+     */
+    public T getValue() {
+        return this.capturingMatcher.getLastValue();
+    }
+
+    /**
+     * Returns all captured values. Use it when capturing varargs or when the verified method was called multiple times.
+     * When varargs method was called multiple times, this method returns merged list of all values from all invocations.
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     *   mock.doSomething(new Person("John");
+     *   mock.doSomething(new Person("Jane");
+     *
+     *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);
+     *   verify(mock, times(2)).doSomething(peopleCaptor.capture());
+     *
+     *   List&lt;Person&gt; capturedPeople = peopleCaptor.getAllValues();
+     *   assertEquals("John", capturedPeople.get(0).getName());
+     *   assertEquals("Jane", capturedPeople.get(1).getName());
+     * </pre>
+     *
+     * Example of capturing varargs:
+     * <pre class="code"><code class="java">
+     *   mock.countPeople(new Person("John"), new Person("Jane"); //vararg method
+     *
+     *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);
+     *
+     *   verify(mock).countPeople(peopleCaptor.capture());
+     *
+     *   List expected = asList(new Person("John"), new Person("Jane"));
+     *   assertEquals(expected, peopleCaptor.getAllValues());
+     * </code></pre>
+     * See more examples in javadoc for {@link ArgumentCaptor} class.
+     *
+     * @return captured argument value
+     */
+    public List<T> getAllValues() {
+        return this.capturingMatcher.getAllValues();
+    }
+
+    /**
+     * Build a new <code>ArgumentCaptor</code>.
+     * <p>
+     * Note that an <code>ArgumentCaptor</code> <b>*don't do any type checks*</b>, it is only there to avoid casting
+     * in your code. This might however change (type checks could be added) in a
+     * future major release.
+     *
+     * @param clazz Type matching the parameter to be captured.
+     * @param <S> Type of clazz
+     * @param <U> Type of object captured by the newly built ArgumentCaptor
+     * @return A new ArgumentCaptor
+     */
+    public static <U,S extends U> ArgumentCaptor<U> forClass(Class<S> clazz) {
+        return new ArgumentCaptor<U>(clazz);
+    }
+}
diff --git a/src/main/java/org/mockito/ArgumentMatcher.java b/src/main/java/org/mockito/ArgumentMatcher.java
index bfa441d..a1e27c9 100644
--- a/src/main/java/org/mockito/ArgumentMatcher.java
+++ b/src/main/java/org/mockito/ArgumentMatcher.java
@@ -1,92 +1,128 @@
 /*
- * Copyright (c) 2007 Mockito contributors
+ * Copyright (c) 2016 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-
 package org.mockito;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.mockito.internal.util.Decamelizer;
-
 /**
- * Allows creating customized argument matchers. 
+ * Allows creating customized argument matchers.
+ * This API was changed in Mockito 2.1.0 in an effort to decouple Mockito from Hamcrest
+ * and reduce the risk of version incompatibility.
+ * Migration guide is included close to the bottom of this javadoc.
  * <p>
- * ArgumentMatcher is an hamcrest {@link Matcher} with predefined describeTo() method.
- * In case of failure, ArgumentMatcher generates description based on <b>decamelized class name</b> - to promote meaningful class names. 
- * For example <b>StringWithStrongLanguage</b> matcher will generate 'String with strong language' description.
- * You can always override describeTo() method and provide detailed description.
+ * For non-trivial method arguments used in stubbing or verification, you have following options
+ * (in no particular order):
+ * <ul>
+ *     <li>refactor the code so that the interactions with collaborators are easier to test with mocks.
+ *     Perhaps it is possible to pass a different argument to the method so that mocking is easier?
+ *     If stuff is hard to test it usually indicates the design could be better, so do refactor for testability!
+ *     </li>
+ *     <li>don't match the argument strictly, just use one of the lenient argument matchers like
+ *     {@link Mockito#notNull()}. Some times it is better to have a simple test that works than
+ *     a complicated test that seem to work.
+ *     </li>
+ *     <li>implement equals() method in the objects that are used as arguments to mocks.
+ *     Mockito naturally uses equals() for argument matching.
+ *     Many times, this is option is clean and simple.
+ *     </li>
+ *     <li>use {@link ArgumentCaptor} to capture the arguments and perform assertions on their state.
+ *     Useful when you need to verify the arguments. Captor is not useful if you need argument matching for stubbing.
+ *     Many times, this option leads to clean and readable tests with fine-grained validation of arguments.
+ *     </li>
+ *     <li>use customized argument matchers by implementing {@link ArgumentMatcher} interface
+ *     and passing the implementation to the {@link Mockito#argThat} method.
+ *     This option is useful if custom matcher is needed for stubbing and can be reused a lot.
+ *     Note that {@link Mockito#argThat} demonstrates <b>NullPointerException</b> auto-unboxing caveat.
+ *     </li>
+ *     <li>use an instance of hamcrest matcher and pass it to
+ *     {@link org.mockito.hamcrest.MockitoHamcrest#argThat(org.hamcrest.Matcher)}
+ *     Useful if you already have a hamcrest matcher. Reuse and win!
+ *     Note that {@link org.mockito.hamcrest.MockitoHamcrest#argThat(org.hamcrest.Matcher)} demonstrates <b>NullPointerException</b> auto-unboxing caveat.
+ *     </li>
+ *     <li>Java 8 only - use a lambda in place of an {@link ArgumentMatcher} since {@link ArgumentMatcher}
+ *     is effectively a functional interface. A lambda can be used with the {@link Mockito#argThat} method.</li>
+ * </ul>
+ *
  * <p>
- * Use {@link Matchers#argThat} method and pass an instance of hamcrest {@link Matcher}, e.g:
- * 
+ * Implementations of this interface can be used with {@link Matchers#argThat} method.
+ * Use <code>toString()</code> method for description of the matcher
+ * - it is printed in verification errors.
+ *
  * <pre class="code"><code class="java">
- * class IsListOfTwoElements extends ArgumentMatcher&lt;List&gt; {
- *     public boolean matches(Object list) {
- *         return ((List) list).size() == 2;
+ * class ListOfTwoElements implements ArgumentMatcher&lt;List&gt; {
+ *     public boolean matches(List list) {
+ *         return list.size() == 2;
+ *     }
+ *     public String toString() {
+ *         //printed in verification errors
+ *         return "[list of 2 elements]";
  *     }
  * }
- * 
+ *
  * List mock = mock(List.class);
- * 
- * when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);
- * 
+ *
+ * when(mock.addAll(argThat(new ListOfTwoElements))).thenReturn(true);
+ *
  * mock.addAll(Arrays.asList(&quot;one&quot;, &quot;two&quot;));
- * 
- * verify(mock).addAll(argThat(new IsListOfTwoElements()));
+ *
+ * verify(mock).addAll(argThat(new ListOfTwoElements()));
  * </code></pre>
- * 
- * To keep it readable you may want to extract method, e.g:
- * 
+ *
+ * To keep it readable you can extract method, e.g:
+ *
  * <pre class="code"><code class="java">
- *   verify(mock).addAll(<b>argThat(new IsListOfTwoElements())</b>);
+ *   verify(mock).addAll(<b>argThat(new ListOfTwoElements())</b>);
  *   //becomes
  *   verify(mock).addAll(<b>listOfTwoElements()</b>);
  * </code></pre>
  *
- * <b>Warning:</b> Be reasonable with using complicated argument matching, especially custom argument matchers, as it can make the test less readable. 
- * Sometimes it's better to implement equals() for arguments that are passed to mocks 
- * (Mockito naturally uses equals() for argument matching). 
- * This can make the test cleaner. 
+ * In Java 8 you can treat ArgumentMatcher as a functional interface
+ * and use a lambda, e.g.:
+ *
+ * <pre class="code"><code class="java">
+ *   verify(mock).addAll(<b>argThat(list -> list.size() == 2)</b>);
+ * </code></pre>
+ *
  * <p>
- * Also, <b>sometimes {@link ArgumentCaptor} may be a better fit</b> than custom matcher.
- * For example, if custom argument matcher is not likely to be reused
- * or you just need it to assert on argument values to complete verification of behavior.
- * <p>
- * Read more about other matchers in javadoc for {@link Matchers} class
- * 
+ * Read more about other matchers in javadoc for {@link Matchers} class.
+ * <h2>2.1.0 migration guide</h2>
+ *
+ * All existing custom implementations of <code>ArgumentMatcher</code> will no longer compile.
+ * All locations where hamcrest matchers are passed to <code>argThat()</code> will no longer compile.
+ * There are 2 approaches to fix the problems:
+ * <ul>
+ * <li>a) Refactor the hamcrest matcher to Mockito matcher:
+ * Use "implements ArgumentMatcher" instead of "extends ArgumentMatcher".
+ * Then refactor <code>describeTo()</code> method into <code>toString()</code> method.
+ * </li>
+ * <li>
+ * b) Use <code>org.mockito.hamcrest.MockitoHamcrest.argThat()</code> instead of <code>Mockito.argThat()</code>.
+ * Ensure that there is <a href="http://hamcrest.org/JavaHamcrest/">hamcrest</a> dependency on classpath
+ * (Mockito does not depend on hamcrest any more).
+ *
+ * </li>
+ * </ul>
+ * What option is right for you? If you don't mind compile dependency to hamcrest
+ * then option b) is probably right for you.
+ * Your choice should not have big impact and is fully reversible -
+ * you can choose different option in future (and refactor the code)
+ *
  * @param <T> type of argument
+ * @since 2.1.0
  */
-public abstract class ArgumentMatcher<T> extends BaseMatcher<T> {
-
-    private static final long serialVersionUID = -2145234737829370369L;
+public interface ArgumentMatcher<T> {
 
     /**
-     * Returns whether this matcher accepts the given argument.
+     * Informs if this matcher accepts the given argument.
      * <p>
      * The method should <b>never</b> assert if the argument doesn't match. It
      * should only return false.
-     * 
+     * <p>
+     * See the example in the top level javadoc for {@link ArgumentMatcher}
+     *
      * @param argument
      *            the argument
-     * @return whether this matcher accepts the given argument.
+     * @return true if this matcher accepts the given argument.
      */
-    public abstract boolean matches(Object argument);
-
-    /**
-     * By default this method decamelizes matchers name to promote meaningful names for matchers.
-     * <p>
-     * For example <b>StringWithStrongLanguage</b> matcher will generate 'String with strong language' description in case of failure.
-     * <p>
-     * You might want to override this method to
-     * provide more specific description of the matcher (useful when
-     * verification failures are reported).
-     * 
-     * @param description the description to which the matcher description is
-     * appended.
-     */
-    public void describeTo(Description description) {
-        String className = getClass().getSimpleName();
-        description.appendText(Decamelizer.decamelizeMatcher(className));
-    }
-}
\ No newline at end of file
+    boolean matches(T argument);
+}
diff --git a/src/main/java/org/mockito/ArgumentMatchers.java b/src/main/java/org/mockito/ArgumentMatchers.java
new file mode 100644
index 0000000..a28eaaf
--- /dev/null
+++ b/src/main/java/org/mockito/ArgumentMatchers.java
@@ -0,0 +1,1323 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.mockito.internal.matchers.Any;
+import org.mockito.internal.matchers.Contains;
+import org.mockito.internal.matchers.EndsWith;
+import org.mockito.internal.matchers.Equals;
+import org.mockito.internal.matchers.InstanceOf;
+import org.mockito.internal.matchers.Matches;
+import org.mockito.internal.matchers.NotNull;
+import org.mockito.internal.matchers.Null;
+import org.mockito.internal.matchers.Same;
+import org.mockito.internal.matchers.StartsWith;
+import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
+import org.mockito.internal.util.Primitives;
+
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+import static org.mockito.internal.util.Primitives.defaultValue;
+
+/**
+ * Allow flexible verification or stubbing. See also {@link AdditionalMatchers}.
+ *
+ * <p>
+ * {@link Mockito} extends ArgumentMatchers so to get access to all matchers just import Mockito class statically.
+ *
+ * <pre class="code"><code class="java">
+ * //stubbing using anyInt() argument matcher
+ * when(mockedList.get(anyInt())).thenReturn("element");
+ *
+ * //following prints "element"
+ * System.out.println(mockedList.get(999));
+ *
+ * //you can also verify using argument matcher
+ * verify(mockedList).get(anyInt());
+ * </code></pre>
+ *
+ * <p>
+ * Since Mockito <code>any(Class)</code> and <code>anyInt</code> family matchers perform a type check, thus they won't
+ * match <code>null</code> arguments. Instead use the <code>isNull</code> matcher.
+ *
+ * <pre class="code"><code class="java">
+ * // stubbing using anyBoolean() argument matcher
+ * when(mock.dryRun(anyBoolean())).thenReturn("state");
+ *
+ * // below the stub won't match, and won't return "state"
+ * mock.dryRun(null);
+ *
+ * // either change the stub
+ * when(mock.dryRun(isNull())).thenReturn("state");
+ * mock.dryRun(null); // ok
+ *
+ * // or fix the code ;)
+ * when(mock.dryRun(anyBoolean())).thenReturn("state");
+ * mock.dryRun(true); // ok
+ *
+ * </code></pre>
+ *
+ * The same apply for verification.
+ * </p>
+ *
+ *
+ * Scroll down to see all methods - full list of matchers.
+ *
+ * <p>
+ * <b>Warning:</b><br/>
+ *
+ * If you are using argument matchers, <b>all arguments</b> have to be provided by matchers.
+ *
+ * E.g: (example shows verification but the same applies to stubbing):
+ * </p>
+ *
+ * <pre class="code"><code class="java">
+ * verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);
+ * //above is correct - eq() is also an argument matcher
+ *
+ * verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);
+ * //above is incorrect - exception will be thrown because third argument is given without argument matcher.
+ * </code></pre>
+ *
+ * <p>
+ * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.
+ * Internally, they record a matcher on a stack and return a dummy value (usually null).
+ * This implementation is due to static type safety imposed by java compiler.
+ * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.
+ * </p>
+ *
+ * <h1>Additional matchers</h1>
+ * <p>
+ * The class {@link AdditionalMatchers} offers rarely used matchers, although they can be useful, when
+ * it is useful to combine multiple matchers or when it is useful to negate a matcher necessary.
+ * </p>
+ *
+ * <h1>Custom Argument ArgumentMatchers</h1>
+ * <p>
+ * It is important to understand the use cases and available options for dealing with non-trivial arguments
+ * <b>before</b> implementing custom argument matchers. This way, you can select the best possible approach
+ * for given scenario and produce highest quality test (clean and maintainable).
+ * Please read on in the javadoc for {@link ArgumentMatcher} to learn about approaches and see the examples.
+ * </p>
+ *
+ * @see AdditionalMatchers
+ */
+@SuppressWarnings("unchecked")
+public class ArgumentMatchers {
+
+    /**
+     * Matches <strong>anything</strong>, including nulls and varargs.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * This is an alias of: {@link #anyObject()} and {@link #any(java.lang.Class)}
+     * </p>
+     *
+     * <p>
+     * <strong>Notes : </strong><br/>
+     * <ul>
+     *     <li>For primitive types use {@link #anyChar()} family or {@link #isA(Class)} or {@link #any(Class)}.</li>
+     *     <li>Since mockito 2.1.0 {@link #any(Class)} is not anymore an alias of this method.</li>
+     * </ul>
+     * </p>
+     *
+     * @return <code>null</code>.
+     *
+     * @see #any(Class)
+     * @see #anyObject()
+     * @see #anyVararg()
+     * @see #anyChar()
+     * @see #anyInt()
+     * @see #anyBoolean()
+     * @see #anyCollectionOf(Class)
+     */
+    public static <T> T any() {
+        return anyObject();
+    }
+
+    /**
+     * Matches anything, including <code>null</code>.
+     *
+     * <p>
+     * This is an alias of: {@link #any()} and {@link #any(java.lang.Class)}.
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>null</code>.
+     * @see #any()
+     * @see #any(Class)
+     * @see #notNull()
+     * @see #notNull(Class)
+     * @deprecated This will be removed in Mockito 3.0 (which will be java 8 only)
+     */
+    @Deprecated
+    public static <T> T anyObject() {
+        reportMatcher(Any.ANY);
+        return null;
+    }
+
+    /**
+     * Matches any object of given type, excluding nulls.
+     *
+     * <p>
+     * This matcher will perform a type check with the given type, thus excluding values.
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     *
+     * This is an alias of: {@link #isA(Class)}}
+     * </p>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null instance of <code></code>, thus <code>null</code> is not anymore a valid value.
+     * As reference are nullable, the suggested API to <strong>match</strong> <code>null</code>
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p><strong>Notes : </strong><br/>
+     * <ul>
+     *     <li>For primitive types use {@link #anyChar()} family.</li>
+     *     <li>Since Mockito 2.1.0 this method will perform a type check thus <code>null</code> values are not authorized.</li>
+     *     <li>Since mockito 2.1.0 {@link #any()} and {@link #anyObject()} are not anymore aliases of this method.</li>
+     * </ul>
+     * </p>
+     *
+     * @param <T> The accepted type
+     * @param type the class of the accepted type.
+     * @return <code>null</code>.
+     * @see #any()
+     * @see #anyObject()
+     * @see #anyVararg()
+     * @see #isA(Class)
+     * @see #notNull()
+     * @see #notNull(Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static <T> T any(Class<T> type) {
+        reportMatcher(new InstanceOf.VarArgAware(type, "<any " + type.getCanonicalName() + ">"));
+        return defaultValue(type);
+    }
+
+    /**
+     * <code>Object</code> argument that implements the given class.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param <T>  the accepted type.
+     * @param type the class of the accepted type.
+     * @return <code>null</code>.
+     * @see #any(Class)
+     */
+    public static <T> T isA(Class<T> type) {
+        reportMatcher(new InstanceOf(type));
+        return defaultValue(type);
+    }
+
+    /**
+     * Any vararg, meaning any number and values of arguments.
+     *
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     * //verification:
+     * mock.foo(1, 2);
+     * mock.foo(1, 2, 3, 4);
+     *
+     * verify(mock, times(2)).foo(anyVararg());
+     *
+     * //stubbing:
+     * when(mock.foo(anyVararg()).thenReturn(100);
+     *
+     * //prints 100
+     * System.out.println(mock.foo(1, 2));
+     * //also prints 100
+     * System.out.println(mock.foo(1, 2, 3, 4));
+     * </code></pre>
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>null</code>.
+     * @see #any()
+     * @see #any(Class)
+     * @deprecated as of 2.1.0 use {@link #any()}
+     */
+    @Deprecated
+    public static <T> T anyVararg() {
+        any();
+        return null;
+    }
+
+    /**
+     * Any <code>boolean</code> or <strong>non-null</strong> <code>Boolean</code>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Boolean</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>false</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static boolean anyBoolean() {
+        reportMatcher(new InstanceOf(Boolean.class, "<any boolean>"));
+        return false;
+    }
+
+    /**
+     * Any <code>byte</code> or <strong>non-null</strong> <code>Byte</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Byte</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static byte anyByte() {
+        reportMatcher(new InstanceOf(Byte.class, "<any byte>"));
+        return 0;
+    }
+
+    /**
+     * Any <code>char</code> or <strong>non-null</strong> <code>Character</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Character</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static char anyChar() {
+        reportMatcher(new InstanceOf(Character.class, "<any char>"));
+        return 0;
+    }
+
+    /**
+     * Any int or <strong>non-null</strong> <code>Integer</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Integer</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static int anyInt() {
+        reportMatcher(new InstanceOf(Integer.class, "<any integer>"));
+        return 0;
+    }
+
+    /**
+     * Any <code>long</code> or <strong>non-null</strong> <code>Long</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Long</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static long anyLong() {
+        reportMatcher(new InstanceOf(Long.class, "<any long>"));
+        return 0;
+    }
+
+    /**
+     * Any <code>float</code> or <strong>non-null</strong> <code>Float</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Float</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static float anyFloat() {
+        reportMatcher(new InstanceOf(Float.class, "<any float>"));
+        return 0;
+    }
+
+    /**
+     * Any <code>double</code> or <strong>non-null</strong> <code>Double</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Double</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static double anyDouble() {
+        reportMatcher(new InstanceOf(Double.class, "<any double>"));
+        return 0;
+    }
+
+    /**
+     * Any <code>short</code> or <strong>non-null</strong> <code>Short</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow valued <code>Short</code>, thus <code>null</code> is not anymore a valid value.
+     * As primitive wrappers are nullable, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return <code>0</code>.
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static short anyShort() {
+        reportMatcher(new InstanceOf(Short.class, "<any short>"));
+        return 0;
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>String</code>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>String</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return empty String ("")
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static String anyString() {
+        reportMatcher(new InstanceOf(String.class, "<any string>"));
+        return "";
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>List</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>List</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return empty List.
+     * @see #anyListOf(Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static <T> List<T> anyList() {
+        reportMatcher(new InstanceOf(List.class, "<any List>"));
+        return new ArrayList<T>(0);
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>List</code>.
+     *
+     * Generic friendly alias to {@link ArgumentMatchers#anyList()}. It's an alternative to
+     * <code>&#064;SuppressWarnings("unchecked")</code> to keep code clean of compiler warnings.
+     *
+     * <p>
+     * This method doesn't do type checks of the list content with the given type parameter, it is only there
+     * to avoid casting in the code.
+     * </p>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>List</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @param clazz Type owned by the list to avoid casting
+     * @return empty List.
+     * @see #anyList()
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> List<T> anyListOf(Class<T> clazz) {
+        return anyList();
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Set</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Set</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return empty Set
+     * @see #anySetOf(Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static <T> Set<T> anySet() {
+        reportMatcher(new InstanceOf(Set.class, "<any set>"));
+        return new HashSet<T>(0);
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Set</code>.
+     *
+     * <p>
+     * Generic friendly alias to {@link ArgumentMatchers#anySet()}.
+     * It's an alternative to <code>&#064;SuppressWarnings("unchecked")</code> to keep code clean of compiler warnings.
+     * </p>
+     *
+     * <p>
+     * This method doesn't do type checks of the set content with the given type parameter, it is only there
+     * to avoid casting in the code.
+     * </p>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Set</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @param clazz Type owned by the Set to avoid casting
+     * @return empty Set
+     * @see #anySet()
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> Set<T> anySetOf(Class<T> clazz) {
+        return anySet();
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Map</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Map</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return empty Map.
+     * @see #anyMapOf(Class, Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static <K, V> Map<K, V> anyMap() {
+        reportMatcher(new InstanceOf(Map.class, "<any map>"));
+        return new HashMap<K, V>(0);
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Map</code>.
+     *
+     * <p>
+     * Generic friendly alias to {@link ArgumentMatchers#anyMap()}.
+     * It's an alternative to <code>&#064;SuppressWarnings("unchecked")</code> to keep code clean of compiler warnings.
+     * </p>
+     *
+     * <p>
+     * This method doesn't do type checks of the map content with the given type parameter, it is only there
+     * to avoid casting in the code.
+     * </p>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Map</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @param keyClazz   Type of the map key to avoid casting
+     * @param valueClazz Type of the value to avoid casting
+     * @return empty Map.
+     * @see #anyMap()
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <K, V> Map<K, V> anyMapOf(Class<K> keyClazz, Class<V> valueClazz) {
+        return anyMap();
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Collection</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Collection</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code>
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return empty Collection.
+     * @see #anyCollectionOf(Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static <T> Collection<T> anyCollection() {
+        reportMatcher(new InstanceOf(Collection.class, "<any collection>"));
+        return new ArrayList<T>(0);
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Collection</code>.
+     *
+     * <p>
+     * Generic friendly alias to {@link ArgumentMatchers#anyCollection()}.
+     * It's an alternative to <code>&#064;SuppressWarnings("unchecked")</code> to keep code clean of compiler warnings.
+     * </p>
+     *
+     * <p>
+     * This method doesn't do type checks of the collection content with the given type parameter, it is only there
+     * to avoid casting in the code.
+     * </p>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Collection</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code>
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @param clazz Type owned by the collection to avoid casting
+     * @return empty Collection.
+     * @see #anyCollection()
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> Collection<T> anyCollectionOf(Class<T> clazz) {
+        return anyCollection();
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Iterable</code>.
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>Iterable</code>.
+     * As this is a nullable reference, the suggested API to <strong>match</strong> <code>null</code>
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @return empty Iterable.
+     * @see #anyIterableOf(Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @since 2.1.0
+     */
+    public static <T> Iterable<T> anyIterable() {
+        reportMatcher(new InstanceOf(Iterable.class, "<any iterable>"));
+        return new ArrayList<T>(0);
+    }
+
+    /**
+     * Any <strong>non-null</strong> <code>Iterable</code>.
+     *
+     * <p>
+     * Generic friendly alias to {@link ArgumentMatchers#anyIterable()}.
+     * It's an alternative to <code>&#064;SuppressWarnings("unchecked")</code> to keep code clean of compiler warnings.
+     * </p>
+     *
+     * <p>
+     * This method doesn't do type checks of the iterable content with the given type parameter, it is only there
+     * to avoid casting in the code.
+     * </p>
+     *
+     * <p>
+     * Since Mockito 2.1.0, only allow non-null <code>String</code>.
+     * As strings are nullable reference, the suggested API to <strong>match</strong> <code>null</code> wrapper
+     * would be {@link #isNull()}. We felt this change would make tests harness much safer that it was with Mockito
+     * 1.x.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class.
+     * </p>
+     *
+     * @param clazz Type owned by the collection to avoid casting
+     * @return empty Iterable.
+     * @see #anyIterable()
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @since 2.1.0
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> Iterable<T> anyIterableOf(Class<T> clazz) {
+        return anyIterable();
+    }
+
+
+
+    /**
+     * <code>boolean</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static boolean eq(boolean value) {
+        reportMatcher(new Equals(value));
+        return false;
+    }
+
+    /**
+     * <code>byte</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static byte eq(byte value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * <code>char</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static char eq(char value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * <code>double</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static double eq(double value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * <code>float</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static float eq(float value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * <code>int</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static int eq(int value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * <code>long</code> argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static long eq(long value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * <code>short</code> argument that is equal to the given value.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param value the given value.
+     * @return <code>0</code>.
+     */
+    public static short eq(short value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Object argument that is equal to the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value the given value.
+     * @return <code>null</code>.
+     */
+    public static <T> T eq(T value) {
+        reportMatcher(new Equals(value));
+        if (value == null)
+            return null;
+        return (T) Primitives.defaultValue(value.getClass());
+    }
+
+    /**
+     * Object argument that is reflection-equal to the given value with support for excluding
+     * selected fields from a class.
+     *
+     * <p>
+     * This matcher can be used when equals() is not implemented on compared objects.
+     * Matcher uses java reflection API to compare fields of wanted and actual object.
+     * </p>
+     *
+     * <p>
+     * Works similarly to <code>EqualsBuilder.reflectionEquals(this, other, exlucdeFields)</code> from
+     * apache commons library.
+     * <p>
+     * <b>Warning</b> The equality check is shallow!
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param value         the given value.
+     * @param excludeFields fields to exclude, if field does not exist it is ignored.
+     * @return <code>null</code>.
+     */
+    public static <T> T refEq(T value, String... excludeFields) {
+        reportMatcher(new ReflectionEquals(value, excludeFields));
+        return null;
+    }
+
+    /**
+     * Object argument that is the same as the given value.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param <T>   the type of the object, it is passed through to prevent casts.
+     * @param value the given value.
+     * @return <code>null</code>.
+     */
+    public static <T> T same(T value) {
+        reportMatcher(new Same(value));
+        if (value == null)
+            return null;
+        return (T) Primitives.defaultValue(value.getClass());
+    }
+
+    /**
+     * <code>null</code> argument.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @return <code>null</code>.
+     * @see #isNull(Class)
+     * @see #isNotNull()
+     * @see #isNotNull(Class)
+     */
+    public static <T> T isNull() {
+        reportMatcher(Null.NULL);
+        return null;
+    }
+
+    /**
+     * <code>null</code> argument.
+     *
+     * <p>
+     * The class argument is provided to avoid casting.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param clazz Type to avoid casting
+     * @return <code>null</code>.
+     * @see #isNull()
+     * @see #isNotNull()
+     * @see #isNotNull(Class)
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> T isNull(Class<T> clazz) {
+        return isNull();
+    }
+
+    /**
+     * Not <code>null</code> argument.
+     *
+     * <p>
+     * Alias to {@link ArgumentMatchers#isNotNull()}
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @return <code>null</code>.
+     */
+    public static <T> T notNull() {
+        reportMatcher(NotNull.NOT_NULL);
+        return null;
+    }
+
+    /**
+     * Not <code>null</code> argument, not necessary of the given class.
+     *
+     * <p>
+     * The class argument is provided to avoid casting.
+     *
+     * Alias to {@link ArgumentMatchers#isNotNull(Class)}
+     * <p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param clazz Type to avoid casting
+     * @return <code>null</code>.
+     * @see #isNotNull()
+     * @see #isNull()
+     * @see #isNull(Class)
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> T notNull(Class<T> clazz) {
+        return notNull();
+    }
+
+    /**
+     * Not <code>null</code> argument.
+     *
+     * <p>
+     * Alias to {@link ArgumentMatchers#notNull()}
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @return <code>null</code>.
+     * @see #isNotNull(Class)
+     * @see #isNull()
+     * @see #isNull(Class)
+     */
+    public static <T> T isNotNull() {
+        return notNull();
+    }
+
+    /**
+     * Not <code>null</code> argument, not necessary of the given class.
+     *
+     * <p>
+     * The class argument is provided to avoid casting.
+     * Alias to {@link ArgumentMatchers#notNull(Class)}
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param clazz Type to avoid casting
+     * @return <code>null</code>.
+     * @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
+     * friendliness to avoid casting, this is not anymore needed in Java 8.
+     */
+    public static <T> T isNotNull(Class<T> clazz) {
+        return notNull(clazz);
+    }
+
+
+    /**
+     * Argument that is either <code>null</code> or of the given type.
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     * </p>
+     *
+     * @param clazz Type to avoid casting
+     * @return <code>null</code>.
+     */
+    public static <T> T nullable(Class<T> clazz) {
+        AdditionalMatchers.or(isNull(), isA(clazz));
+        return  (T) Primitives.defaultValue(clazz);
+    }
+
+    /**
+     * <code>String</code> argument that contains the given substring.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param substring the substring.
+     * @return empty String ("").
+     */
+    public static String contains(String substring) {
+        reportMatcher(new Contains(substring));
+        return "";
+    }
+
+    /**
+     * <code>String</code> argument that matches the given regular expression.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param regex the regular expression.
+     * @return empty String ("").
+     *
+     * @see AdditionalMatchers#not(boolean)
+     */
+    public static String matches(String regex) {
+        reportMatcher(new Matches(regex));
+        return "";
+    }
+
+    /**
+     * <code>Pattern</code> argument that matches the given regular expression.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param pattern the regular expression pattern.
+     * @return empty String ("").
+     *
+     * @see AdditionalMatchers#not(boolean)
+     */
+    public static String matches(Pattern pattern) {
+        reportMatcher(new Matches(pattern));
+        return "";
+    }
+
+    /**
+     * <code>String</code> argument that ends with the given suffix.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param suffix the suffix.
+     * @return empty String ("").
+     */
+    public static String endsWith(String suffix) {
+        reportMatcher(new EndsWith(suffix));
+        return "";
+    }
+
+    /**
+     * <code>String</code> argument that starts with the given prefix.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param prefix the prefix.
+     * @return empty String ("").
+     */
+    public static String startsWith(String prefix) {
+        reportMatcher(new StartsWith(prefix));
+        return "";
+    }
+
+    /**
+     * Allows creating custom argument matchers.
+     *
+     * <p>
+     * This API has changed in 2.1.0, please read {@link ArgumentMatcher} for rationale and migration guide.
+     * <b>NullPointerException</b> auto-unboxing caveat is described below.
+     * </p>
+     *
+     * <p>
+     * It is important to understand the use cases and available options for dealing with non-trivial arguments
+     * <b>before</b> implementing custom argument matchers. This way, you can select the best possible approach
+     * for given scenario and produce highest quality test (clean and maintainable).
+     * Please read the documentation for {@link ArgumentMatcher} to learn about approaches and see the examples.
+     * </p>
+     *
+     * <p>
+     * <b>NullPointerException</b> auto-unboxing caveat.
+     * In rare cases when matching primitive parameter types you <b>*must*</b> use relevant intThat(), floatThat(), etc. method.
+     * This way you will avoid <code>NullPointerException</code> during auto-unboxing.
+     * Due to how java works we don't really have a clean way of detecting this scenario and protecting the user from this problem.
+     * Hopefully, the javadoc describes the problem and solution well.
+     * If you have an idea how to fix the problem, let us know via the mailing list or the issue tracker.
+     * </p>
+     *
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatcher} class
+     * </p>
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>null</code>.
+     */
+    public static <T> T argThat(ArgumentMatcher<T> matcher) {
+        reportMatcher(matcher);
+        return null;
+    }
+
+    /**
+     * Allows creating custom <code>char</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>char</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static char charThat(ArgumentMatcher<Character> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    /**
+     * Allows creating custom <code>boolean</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>boolean</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>false</code>.
+     */
+    public static boolean booleanThat(ArgumentMatcher<Boolean> matcher) {
+        reportMatcher(matcher);
+        return false;
+    }
+
+    /**
+     * Allows creating custom <code>byte</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>byte</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static byte byteThat(ArgumentMatcher<Byte> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    /**
+     * Allows creating custom <code>short</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>short</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static short shortThat(ArgumentMatcher<Short> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    /**
+     * Allows creating custom <code>int</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>int</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static int intThat(ArgumentMatcher<Integer> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    /**
+     * Allows creating custom <code>long</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>long</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static long longThat(ArgumentMatcher<Long> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    /**
+     * Allows creating custom <code>float</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>float</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static float floatThat(ArgumentMatcher<Float> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    /**
+     * Allows creating custom <code>double</code> argument matchers.
+     *
+     * Note that {@link #argThat} will not work with primitive <code>double</code> matchers due to <code>NullPointerException</code> auto-unboxing caveat.
+     * <p>
+     * See examples in javadoc for {@link ArgumentMatchers} class
+     *
+     * @param matcher decides whether argument matches
+     * @return <code>0</code>.
+     */
+    public static double doubleThat(ArgumentMatcher<Double> matcher) {
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    private static void reportMatcher(ArgumentMatcher<?> matcher) {
+        mockingProgress().getArgumentMatcherStorage().reportMatcher(matcher);
+    }
+}
diff --git a/src/main/java/org/mockito/BDDMockito.java b/src/main/java/org/mockito/BDDMockito.java
index b1b5e5d..9090fa8 100644
--- a/src/main/java/org/mockito/BDDMockito.java
+++ b/src/main/java/org/mockito/BDDMockito.java
@@ -1,416 +1,529 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.OngoingStubbing;

-import org.mockito.stubbing.Stubber;

-import org.mockito.verification.VerificationMode;

-

-/**

- * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.

- * This is exactly how we write our tests and we warmly encourage you to do so!

- * <p>

- * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>

- * <p>

- * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.

- * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.

- * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.

- * Now it really nicely integrates with the <b>given</b> component of a BDD style test!

- * <p>

- * Here is how the test might look like:

- * <pre class="code"><code class="java">

- * import static org.mockito.BDDMockito.*;

- *

- * Seller seller = mock(Seller.class);

- * Shop shop = new Shop(seller);

- *

- * public void shouldBuyBread() throws Exception {

- *   //given

- *   given(seller.askForBread()).willReturn(new Bread());

- *

- *   //when

- *   Goods goods = shop.buyBread();

- *

- *   //then

- *   assertThat(goods, containBread());

- * }

- * </code></pre>

- *

- * Stubbing voids with throwables:

- * <pre class="code"><code class="java">

- *   //given

- *   willThrow(new RuntimeException("boo")).given(mock).foo();

- *

- *   //when

- *   Result result = systemUnderTest.perform();

- *

- *   //then

- *   assertEquals(failure, result);

- * </code></pre>

- * <p>

- * For BDD style mock verification take a look at {@link Then} in action:

- * <pre class="code"><code class="java">

- *   person.ride(bike);

- *   person.ride(bike);

- *

- *   then(person).should(times(2)).ride(bike);

- * </code></pre>

- *

- * One of the purposes of BDDMockito is also to show how to tailor the mocking syntax to a different programming style.

- *

- * @since 1.8.0

- */

-@SuppressWarnings("unchecked")

-public class BDDMockito extends Mockito {

-

-    /**

-     * See original {@link OngoingStubbing}

-     * @since 1.8.0

-     */

-    public interface BDDMyOngoingStubbing<T> {

-

-        /**

-         * See original {@link OngoingStubbing#thenAnswer(Answer)}

-         * @since 1.8.0

-         */

-        BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer);

-

-        /**

-         * See original {@link OngoingStubbing#then(Answer)}

-         * @since 1.9.0

-         */

-        BDDMyOngoingStubbing<T> will(Answer<?> answer);

-

-        /**

-         * See original {@link OngoingStubbing#thenReturn(Object)}

-         * @since 1.8.0

-         */

-        BDDMyOngoingStubbing<T> willReturn(T value);

-

-        /**

-         * See original {@link OngoingStubbing#thenReturn(Object, Object[])}

-         * @since 1.8.0

-         */

-        BDDMyOngoingStubbing<T> willReturn(T value, T... values);

-

-        /**

-         * See original {@link OngoingStubbing#thenThrow(Throwable...)}

-         * @since 1.8.0

-         */

-        BDDMyOngoingStubbing<T> willThrow(Throwable... throwables);

-

-        /**

-         * See original {@link OngoingStubbing#thenThrow(Class[])}

-         * @since 1.9.0

-         */

-        BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable>... throwableClasses);

-

-        /**

-         * See original {@link OngoingStubbing#thenCallRealMethod()}

-         * @since 1.9.0

-         */

-        BDDMyOngoingStubbing<T> willCallRealMethod();

-

-        /**

-         * See original {@link OngoingStubbing#getMock()}

-         * @since 1.9.0

-         */

-        <M> M getMock();

-    }

-

-    /**

-     * @deprecated not part of the public API, use {@link BDDMyOngoingStubbing} instead.

-     */

-    @Deprecated

-    public static class BDDOngoingStubbingImpl<T> implements BDDMyOngoingStubbing<T> {

-

-        private final OngoingStubbing<T> mockitoOngoingStubbing;

-

-        public BDDOngoingStubbingImpl(OngoingStubbing<T> ongoingStubbing) {

-            this.mockitoOngoingStubbing = ongoingStubbing;

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDMyOngoingStubbing#willAnswer(Answer)

-         */

-        public BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer) {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenAnswer(answer));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDMyOngoingStubbing#will(Answer)

-         */

-        public BDDMyOngoingStubbing<T> will(Answer<?> answer) {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.then(answer));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDMyOngoingStubbing#willReturn(java.lang.Object)

-         */

-        public BDDMyOngoingStubbing<T> willReturn(T value) {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDMyOngoingStubbing#willReturn(java.lang.Object, T[])

-         */

-        public BDDMyOngoingStubbing<T> willReturn(T value, T... values) {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value, values));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDMyOngoingStubbing#willThrow(java.lang.Throwable[])

-         */

-        public BDDMyOngoingStubbing<T> willThrow(Throwable... throwables) {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwables));

-        }

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDMyOngoingStubbing#willThrow(java.lang.Class[])

-         */

-        public BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable>... throwableClasses) {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwableClasses));

-        }

-

-        public BDDMyOngoingStubbing<T> willCallRealMethod() {

-            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenCallRealMethod());

-        }

-

-        public <M> M getMock() {

-            return (M) mockitoOngoingStubbing.getMock();

-        }

-    }

-

-    /**

-     * see original {@link Mockito#when(Object)}

-     * @since 1.8.0

-     */

-    public static <T> BDDMyOngoingStubbing<T> given(T methodCall) {

-        return new BDDOngoingStubbingImpl<T>(Mockito.when(methodCall));

-    }

-

-    /**

-     * Bdd style verification of mock behavior.

-     *

-     * <pre class="code"><code class="java">

-     *   person.ride(bike);

-     *   person.ride(bike);

-     *

-     *   then(person).should(times(2)).ride(bike);

-     * </code></pre>

-     *

-     * @see #verify(Object)

-     * @see #verify(Object, VerificationMode)

-     * @since 1.10.0

-     */

-    public static <T> Then<T> then(T mock) {

-        return new ThenImpl<T>(mock);

-    }

-

-    /**

-     * Provides fluent way of mock verification.

-     *

-     * @param <T> type of the mock

-     *

-     * @since 1.10.5

-     */

-    public static interface Then<T> {

-

-        /**

-         * @see #verify(Object)

-         * @since 1.10.5

-         */

-        T should();

-

-        /**

-         * @see #verify(Object, VerificationMode)

-         * @since 1.10.5

-         */

-        T should(VerificationMode mode);

-    }

-

-    static class ThenImpl<T> implements Then<T> {

-

-        private final T mock;

-

-        ThenImpl(T mock) {

-            this.mock = mock;

-        }

-

-        /**

-         * @see #verify(Object)

-         * @since 1.10.5

-         */

-        public T should() {

-            return verify(mock);

-        }

-

-        /**

-         * @see #verify(Object, VerificationMode)

-         * @since 1.10.5

-         */

-        public T should(VerificationMode mode) {

-            return verify(mock, mode);

-        }

-    }

-

-    /**

-     * See original {@link Stubber}

-     * @since 1.8.0

-     */

-    public interface BDDStubber {

-        /**

-         * See original {@link Stubber#doAnswer(Answer)}

-         * @since 1.8.0

-         */

-        BDDStubber willAnswer(Answer answer);

-

-        /**

-         * See original {@link Stubber#doNothing()}

-         * @since 1.8.0

-         */

-        BDDStubber willNothing();

-

-        /**

-         * See original {@link Stubber#doReturn(Object)}

-         * @since 1.8.0

-         */

-        BDDStubber willReturn(Object toBeReturned);

-

-        /**

-         * See original {@link Stubber#doThrow(Throwable)}

-         * @since 1.8.0

-         */

-        BDDStubber willThrow(Throwable toBeThrown);

-

-        /**

-         * See original {@link Stubber#doThrow(Class)}

-         * @since 1.9.0

-         */

-        BDDStubber willThrow(Class<? extends Throwable> toBeThrown);

-

-        /**

-         * See original {@link Stubber#doCallRealMethod()}

-         * @since 1.9.0

-         */

-        BDDStubber willCallRealMethod();

-

-        /**

-         * See original {@link Stubber#when(Object)}

-         * @since 1.8.0

-         */

-        <T> T given(T mock);

-    }

-

-    /**

-     * @deprecated not part of the public API, use {@link BDDStubber} instead.

-     */

-    @Deprecated

-    public static class BDDStubberImpl implements BDDStubber {

-

-        private final Stubber mockitoStubber;

-

-        public BDDStubberImpl(Stubber mockitoStubber) {

-            this.mockitoStubber = mockitoStubber;

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#given(java.lang.Object)

-         */

-        public <T> T given(T mock) {

-            return mockitoStubber.when(mock);

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#willAnswer(Answer)

-         */

-        public BDDStubber willAnswer(Answer answer) {

-            return new BDDStubberImpl(mockitoStubber.doAnswer(answer));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#willNothing()

-         */

-        public BDDStubber willNothing() {

-            return new BDDStubberImpl(mockitoStubber.doNothing());

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#willReturn(java.lang.Object)

-         */

-        public BDDStubber willReturn(Object toBeReturned) {

-            return new BDDStubberImpl(mockitoStubber.doReturn(toBeReturned));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#willThrow(java.lang.Throwable)

-         */

-        public BDDStubber willThrow(Throwable toBeThrown) {

-            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#willThrow(Class)

-         */

-        public BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {

-            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));

-        }

-

-        /* (non-Javadoc)

-         * @see BDDMockito.BDDStubber#willCallRealMethod()

-         */

-        public BDDStubber willCallRealMethod() {

-            return new BDDStubberImpl(mockitoStubber.doCallRealMethod());

-        }

-    }

-

-    /**

-     * see original {@link Mockito#doThrow(Throwable)}

-     * @since 1.8.0

-     */

-    public static BDDStubber willThrow(Throwable toBeThrown) {

-        return new BDDStubberImpl(Mockito.doThrow(toBeThrown));

-    }

-

-    /**

-     * see original {@link Mockito#doThrow(Throwable)}

-     * @since 1.9.0

-     */

-    public static BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {

-        return new BDDStubberImpl(Mockito.doThrow(toBeThrown));

-    }

-

-    /**

-     * see original {@link Mockito#doAnswer(Answer)}

-     * @since 1.8.0

-     */

-    public static BDDStubber willAnswer(Answer answer) {

-        return new BDDStubberImpl(Mockito.doAnswer(answer));

-    }

-

-    /**

-     * see original {@link Mockito#doNothing()}

-     * @since 1.8.0

-     */

-    public static BDDStubber willDoNothing() {

-        return new BDDStubberImpl(Mockito.doNothing());

-    }

-

-    /**

-     * see original {@link Mockito#doReturn(Object)}

-     * @since 1.8.0

-     */

-    public static BDDStubber willReturn(Object toBeReturned) {

-        return new BDDStubberImpl(Mockito.doReturn(toBeReturned));

-    }

-

-    /**

-     * see original {@link Mockito#doCallRealMethod()}

-     * @since 1.8.0

-     */

-    public static BDDStubber willCallRealMethod() {

-        return new BDDStubberImpl(Mockito.doCallRealMethod());

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.stubbing.Stubber;
+import org.mockito.verification.VerificationMode;
+
+/**
+ * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.
+ * This is exactly how we write our tests and we warmly encourage you to do so!
+ * <p>
+ * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>
+ * <p>
+ * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.
+ * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.
+ * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.
+ * Now it really nicely integrates with the <b>given</b> component of a BDD style test!
+ * <p>
+ * Here is how the test might look like:
+ * <pre class="code"><code class="java">
+ * import static org.mockito.BDDMockito.*;
+ *
+ * Seller seller = mock(Seller.class);
+ * Shop shop = new Shop(seller);
+ *
+ * public void shouldBuyBread() throws Exception {
+ *   //given
+ *   given(seller.askForBread()).willReturn(new Bread());
+ *
+ *   //when
+ *   Goods goods = shop.buyBread();
+ *
+ *   //then
+ *   assertThat(goods, containBread());
+ * }
+ * </code></pre>
+ *
+ * Stubbing voids with throwables:
+ * <pre class="code"><code class="java">
+ *   //given
+ *   willThrow(new RuntimeException("boo")).given(mock).foo();
+ *
+ *   //when
+ *   Result result = systemUnderTest.perform();
+ *
+ *   //then
+ *   assertEquals(failure, result);
+ * </code></pre>
+ * <p>
+ * For BDD style mock verification take a look at {@link Then} in action:
+ * <pre class="code"><code class="java">
+ *   person.ride(bike);
+ *   person.ride(bike);
+ *
+ *   then(person).should(times(2)).ride(bike);
+ *   then(person).shouldHaveNoMoreInteractions();
+ *   then(police).shouldHaveZeroInteractions();
+ * </code></pre>
+ * <p>
+ * It is also possible to do BDD style {@link InOrder} verification:
+ * <pre class="code"><code class="java">
+ *   InOrder inOrder = inOrder(person);
+ *
+ *   person.drive(car);
+ *   person.ride(bike);
+ *   person.ride(bike);
+ *
+ *   then(person).should(inOrder).drive(car);
+ *   then(person).should(inOrder, times(2)).ride(bike);
+ * </code></pre>
+ * <p>
+ * One of the purposes of BDDMockito is also to show how to tailor the mocking syntax to a different programming style.
+ *
+ * @since 1.8.0
+ */
+@SuppressWarnings("unchecked")
+public class BDDMockito extends Mockito {
+
+    /**
+     * See original {@link OngoingStubbing}
+     * @since 1.8.0
+     */
+    public interface BDDMyOngoingStubbing<T> {
+
+        /**
+         * See original {@link OngoingStubbing#thenAnswer(Answer)}
+         * @since 1.8.0
+         */
+        BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer);
+
+        /**
+         * See original {@link OngoingStubbing#then(Answer)}
+         * @since 1.9.0
+         */
+        BDDMyOngoingStubbing<T> will(Answer<?> answer);
+
+        /**
+         * See original {@link OngoingStubbing#thenReturn(Object)}
+         * @since 1.8.0
+         */
+        BDDMyOngoingStubbing<T> willReturn(T value);
+
+        /**
+         * See original {@link OngoingStubbing#thenReturn(Object, Object[])}
+         * @since 1.8.0
+         */
+        @SuppressWarnings({"unchecked", "varargs"})
+        BDDMyOngoingStubbing<T> willReturn(T value, T... values);
+
+        /**
+         * See original {@link OngoingStubbing#thenThrow(Throwable...)}
+         * @since 1.8.0
+         */
+        BDDMyOngoingStubbing<T> willThrow(Throwable... throwables);
+
+        /**
+         * See original {@link OngoingStubbing#thenThrow(Class)}
+         * @since 2.1.0
+         */
+        BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable> throwableType);
+
+        /**
+         * See original {@link OngoingStubbing#thenThrow(Class, Class[])}
+         * @since 2.1.0
+         */
+        // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation
+        @SuppressWarnings ({"unchecked", "varargs"})
+        BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable> throwableType, Class<? extends Throwable>... throwableTypes);
+
+        /**
+         * See original {@link OngoingStubbing#thenCallRealMethod()}
+         * @since 1.9.0
+         */
+        BDDMyOngoingStubbing<T> willCallRealMethod();
+
+        /**
+         * See original {@link OngoingStubbing#getMock()}
+         * @since 1.9.0
+         */
+        <M> M getMock();
+    }
+
+    private static class BDDOngoingStubbingImpl<T> implements BDDMyOngoingStubbing<T> {
+
+        private final OngoingStubbing<T> mockitoOngoingStubbing;
+
+        public BDDOngoingStubbingImpl(OngoingStubbing<T> ongoingStubbing) {
+            this.mockitoOngoingStubbing = ongoingStubbing;
+        }
+
+        public BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenAnswer(answer));
+        }
+
+        public BDDMyOngoingStubbing<T> will(Answer<?> answer) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.then(answer));
+        }
+
+        public BDDMyOngoingStubbing<T> willReturn(T value) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value));
+        }
+
+        public BDDMyOngoingStubbing<T> willReturn(T value, T... values) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value, values));
+        }
+
+        public BDDMyOngoingStubbing<T> willThrow(Throwable... throwables) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwables));
+        }
+
+        public BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable> throwableType) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwableType));
+        }
+
+        public BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable> throwableType, Class<? extends Throwable>... throwableTypes) {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwableType, throwableTypes));
+        }
+
+        public BDDMyOngoingStubbing<T> willCallRealMethod() {
+            return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenCallRealMethod());
+        }
+
+        public <M> M getMock() {
+            return (M) mockitoOngoingStubbing.getMock();
+        }
+    }
+
+    /**
+     * see original {@link Mockito#when(Object)}
+     * @since 1.8.0
+     */
+    public static <T> BDDMyOngoingStubbing<T> given(T methodCall) {
+        return new BDDOngoingStubbingImpl<T>(Mockito.when(methodCall));
+    }
+
+    /**
+     * Bdd style verification of mock behavior.
+     *
+     * <pre class="code"><code class="java">
+     *   person.ride(bike);
+     *   person.ride(bike);
+     *
+     *   then(person).should(times(2)).ride(bike);
+     * </code></pre>
+     *
+     * @see #verify(Object)
+     * @see #verify(Object, VerificationMode)
+     * @since 1.10.0
+     */
+    public static <T> Then<T> then(T mock) {
+        return new ThenImpl<T>(mock);
+    }
+
+    /**
+     * Provides fluent way of mock verification.
+     *
+     * @param <T> type of the mock
+     *
+     * @since 1.10.5
+     */
+    public interface Then<T> {
+
+        /**
+         * @see #verify(Object)
+         * @since 1.10.5
+         */
+        T should();
+
+        /**
+         * @see #verify(Object, VerificationMode)
+         * @since 1.10.5
+         */
+        T should(VerificationMode mode);
+
+        /**
+         * @see InOrder#verify(Object)
+         * @since 2.1.0
+         */
+        T should(InOrder inOrder);
+
+        /**
+         * @see InOrder#verify(Object, VerificationMode)
+         * @since 2.1.0
+         */
+        T should(InOrder inOrder, VerificationMode mode);
+
+        /**
+         * @see #verifyZeroInteractions(Object...)
+         * @since 2.1.0
+         */
+        void shouldHaveZeroInteractions();
+
+        /**
+         * @see #verifyNoMoreInteractions(Object...)
+         * @since 2.1.0
+         */
+        void shouldHaveNoMoreInteractions();
+    }
+
+    private static class ThenImpl<T> implements Then<T> {
+
+        private final T mock;
+
+        ThenImpl(T mock) {
+            this.mock = mock;
+        }
+
+        /**
+         * @see #verify(Object)
+         * @since 1.10.5
+         */
+        public T should() {
+            return verify(mock);
+        }
+
+        /**
+         * @see #verify(Object, VerificationMode)
+         * @since 1.10.5
+         */
+        public T should(VerificationMode mode) {
+            return verify(mock, mode);
+        }
+
+        /**
+         * @see InOrder#verify(Object)
+         * @since 2.1.0
+         */
+        public T should(InOrder inOrder) {
+            return inOrder.verify(mock);
+        }
+
+        /**
+         * @see InOrder#verify(Object, VerificationMode)
+         * @since 2.1.0
+         */
+        public T should(InOrder inOrder, VerificationMode mode) {
+            return inOrder.verify(mock, mode);
+        }
+
+        /**
+         * @see #verifyZeroInteractions(Object...)
+         * @since 2.1.0
+         */
+        public void shouldHaveZeroInteractions() {
+            verifyZeroInteractions(mock);
+        }
+
+        /**
+         * @see #verifyNoMoreInteractions(Object...)
+         * @since 2.1.0
+         */
+        public void shouldHaveNoMoreInteractions() {
+            verifyNoMoreInteractions(mock);
+        }
+    }
+
+    /**
+     * See original {@link Stubber}
+     * @since 1.8.0
+     */
+    public interface BDDStubber {
+        /**
+         * See original {@link Stubber#doAnswer(Answer)}
+         * @since 1.8.0
+         */
+        BDDStubber willAnswer(Answer<?> answer);
+
+        /**
+         * See original {@link Stubber#doAnswer(Answer)}
+         * @since 1.8.0
+         */
+        BDDStubber will(Answer<?> answer);
+
+        /**
+         * See original {@link Stubber#doNothing()}.
+         *
+         * This method will be removed in version 3.0.0
+         *
+         * @since 1.8.0
+         * @deprecated as of 2.1.0 please use {@link #willDoNothing()} instead
+         */
+        @Deprecated
+        BDDStubber willNothing();
+
+        /**
+         * See original {@link Stubber#doNothing()}
+         * @since 1.10.20
+         */
+        BDDStubber willDoNothing();
+
+        /**
+         * See original {@link Stubber#doReturn(Object)}
+         * @since 2.1.0
+         */
+        BDDStubber willReturn(Object toBeReturned);
+
+        /**
+         * See original {@link Stubber#doReturn(Object)}
+         * @since 2.1.0
+         */
+        @SuppressWarnings({"unchecked", "varargs"})
+        BDDStubber willReturn(Object toBeReturned, Object... nextToBeReturned);
+
+        /**
+         * See original {@link Stubber#doThrow(Throwable...)}
+         * @since 1.8.0
+         */
+        BDDStubber willThrow(Throwable... toBeThrown);
+
+        /**
+         * See original {@link Stubber#doThrow(Class)}
+         * @since 2.1.0
+         */
+        BDDStubber willThrow(Class<? extends Throwable> toBeThrown);
+
+        /**
+         * See original {@link Stubber#doThrow(Class, Class[])}
+         * @since 2.1.0
+         */
+        @SuppressWarnings ({"unchecked", "varargs"})
+        BDDStubber willThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown);
+
+        /**
+         * See original {@link Stubber#doCallRealMethod()}
+         * @since 1.9.0
+         */
+        BDDStubber willCallRealMethod();
+
+        /**
+         * See original {@link Stubber#when(Object)}
+         * @since 1.8.0
+         */
+        <T> T given(T mock);
+    }
+
+    private static class BDDStubberImpl implements BDDStubber {
+
+        private final Stubber mockitoStubber;
+
+        public BDDStubberImpl(Stubber mockitoStubber) {
+            this.mockitoStubber = mockitoStubber;
+        }
+
+        public <T> T given(T mock) {
+            return mockitoStubber.when(mock);
+        }
+
+        public BDDStubber willAnswer(Answer<?> answer) {
+            return new BDDStubberImpl(mockitoStubber.doAnswer(answer));
+        }
+
+        public BDDStubber will(Answer<?> answer) {
+            return new BDDStubberImpl(mockitoStubber.doAnswer(answer));
+        }
+
+        /**
+         * @deprecated please use {@link #willDoNothing()} instead
+         */
+        @Deprecated
+        public BDDStubber willNothing() {
+            return willDoNothing();
+        }
+
+        public BDDStubber willDoNothing() {
+            return new BDDStubberImpl(mockitoStubber.doNothing());
+        }
+
+        public BDDStubber willReturn(Object toBeReturned) {
+            return new BDDStubberImpl(mockitoStubber.doReturn(toBeReturned));
+        }
+
+        public BDDStubber willReturn(Object toBeReturned, Object... nextToBeReturned) {
+            return new BDDStubberImpl(mockitoStubber.doReturn(toBeReturned).doReturn(nextToBeReturned));
+        }
+
+        public BDDStubber willThrow(Throwable... toBeThrown) {
+            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));
+        }
+
+        public BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {
+            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));
+        }
+
+        public BDDStubber willThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown) {
+            return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown, nextToBeThrown));
+        }
+
+        public BDDStubber willCallRealMethod() {
+            return new BDDStubberImpl(mockitoStubber.doCallRealMethod());
+        }
+    }
+
+    /**
+     * see original {@link Mockito#doThrow(Throwable[])}
+     * @since 2.1.0
+     */
+    public static BDDStubber willThrow(Throwable... toBeThrown) {
+        return new BDDStubberImpl(Mockito.doThrow(toBeThrown));
+    }
+
+    /**
+     * see original {@link Mockito#doThrow(Class)}
+     * @since 1.9.0
+     */
+    public static BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {
+        return new BDDStubberImpl(Mockito.doThrow(toBeThrown));
+    }
+
+    /**
+     * see original {@link Mockito#doThrow(Class)}
+     * @since 1.9.0
+     */
+    public static BDDStubber willThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... throwableTypes) {
+        return new BDDStubberImpl(Mockito.doThrow(toBeThrown, throwableTypes));
+    }
+
+    /**
+     * see original {@link Mockito#doAnswer(Answer)}
+     * @since 1.8.0
+     */
+    public static BDDStubber willAnswer(Answer<?> answer) {
+        return new BDDStubberImpl(Mockito.doAnswer(answer));
+    }
+
+    /**
+     * see original {@link Mockito#doAnswer(Answer)}
+     * @since 2.1.0
+     */
+    public static BDDStubber will(Answer<?> answer) {
+        return new BDDStubberImpl(Mockito.doAnswer(answer));
+    }
+
+    /**
+     * see original {@link Mockito#doNothing()}
+     * @since 1.8.0
+     */
+    public static BDDStubber willDoNothing() {
+        return new BDDStubberImpl(Mockito.doNothing());
+    }
+
+    /**
+     * see original {@link Mockito#doReturn(Object)}
+     * @since 1.8.0
+     */
+    public static BDDStubber willReturn(Object toBeReturned) {
+        return new BDDStubberImpl(Mockito.doReturn(toBeReturned));
+    }
+
+    /**
+     * see original {@link Mockito#doReturn(Object, Object...)}
+     * @since 2.1.0
+     */
+    @SuppressWarnings({"unchecked", "varargs"})
+    public static BDDStubber willReturn(Object toBeReturned, Object... toBeReturnedNext) {
+        return new BDDStubberImpl(Mockito.doReturn(toBeReturned, toBeReturnedNext));
+    }
+
+    /**
+     * see original {@link Mockito#doCallRealMethod()}
+     * @since 1.8.0
+     */
+    public static BDDStubber willCallRealMethod() {
+        return new BDDStubberImpl(Mockito.doCallRealMethod());
+    }
+}
diff --git a/src/main/java/org/mockito/Captor.java b/src/main/java/org/mockito/Captor.java
index 30530fb..225bf70 100644
--- a/src/main/java/org/mockito/Captor.java
+++ b/src/main/java/org/mockito/Captor.java
@@ -2,39 +2,39 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito;

-

-import java.lang.annotation.*;

-

-/**

- * Allows shorthand {@link org.mockito.ArgumentCaptor} creation on fields.

- *

- * <p>Example:

- * <pre class="code"><code class="java">

- * public class Test{

- *

- *    &#64;Captor ArgumentCaptor&lt;AsyncCallback&lt;Foo&gt;&gt; captor;

- *

- *    &#64;Before

- *    public void init(){

- *       MockitoAnnotations.initMocks(this);

- *    }

- *

- *    &#64;Test public void shouldDoSomethingUseful() {

- *       //...

- *       verify(mock.doStuff(captor.capture()));

- *       assertEquals("foo", captor.getValue());

- *    }

- * }

- * </code></pre>

- *

- * <p>

- * One of the advantages of using &#64;Captor annotation is that you can avoid warnings related capturing complex generic types.

- *

- * @see ArgumentCaptor

- * @since 1.8.3

- */

-@Retention(RetentionPolicy.RUNTIME)

-@Target(ElementType.FIELD)

-@Documented

-public @interface Captor {}

+package org.mockito;
+
+import java.lang.annotation.*;
+
+/**
+ * Allows shorthand {@link org.mockito.ArgumentCaptor} creation on fields.
+ *
+ * <p>Example:
+ * <pre class="code"><code class="java">
+ * public class Test{
+ *
+ *    &#64;Captor ArgumentCaptor&lt;AsyncCallback&lt;Foo&gt;&gt; captor;
+ *
+ *    &#64;Before
+ *    public void init(){
+ *       MockitoAnnotations.initMocks(this);
+ *    }
+ *
+ *    &#64;Test public void shouldDoSomethingUseful() {
+ *       //...
+ *       verify(mock).doStuff(captor.capture());
+ *       assertEquals("foo", captor.getValue());
+ *    }
+ * }
+ * </code></pre>
+ *
+ * <p>
+ * One of the advantages of using &#64;Captor annotation is that you can avoid warnings related capturing complex generic types.
+ *
+ * @see ArgumentCaptor
+ * @since 1.8.3
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Documented
+public @interface Captor {}
diff --git a/src/main/java/org/mockito/InOrder.java b/src/main/java/org/mockito/InOrder.java
index 5f19eb0..56beafe 100644
--- a/src/main/java/org/mockito/InOrder.java
+++ b/src/main/java/org/mockito/InOrder.java
@@ -9,17 +9,17 @@
 
 /**
  * Allows verification in order. E.g:
- * 
+ *
  * <pre class="code"><code class="java">
  * InOrder inOrder = inOrder(firstMock, secondMock);
- * 
+ *
  * inOrder.verify(firstMock).add("was called first");
  * inOrder.verify(secondMock).add("was called second");
  * </code></pre>
- * 
- * As of Mockito 1.8.4 you can verifyNoMoreInvocations() in order-sensitive way. Read more: {@link InOrder#verifyNoMoreInteractions()}
+ *
+ * As of Mockito 1.8.4 you can verifyNoMoreInteractions() in order-sensitive way. Read more: {@link InOrder#verifyNoMoreInteractions()}
  * <p>
- * 
+ *
  * See examples in javadoc for {@link Mockito} class
  */
 public interface InOrder {
@@ -31,41 +31,41 @@
      * Example:
      * <pre class="code"><code class="java">
      * InOrder inOrder = inOrder(firstMock, secondMock);
-     * 
+     *
      * inOrder.verify(firstMock).someMethod("was called first");
      * inOrder.verify(secondMock).someMethod("was called second");
      * </code></pre>
-     * 
+     *
      * See examples in javadoc for {@link Mockito} class
-     * 
+     *
      * @param mock to be verified
-     * 
+     *
      * @return mock object itself
      */
     <T> T verify(T mock);
 
     /**
      * Verifies interaction in order. E.g:
-     * 
+     *
      * <pre class="code"><code class="java">
      * InOrder inOrder = inOrder(firstMock, secondMock);
-     * 
+     *
      * inOrder.verify(firstMock, times(2)).someMethod("was called first two times");
      * inOrder.verify(secondMock, atLeastOnce()).someMethod("was called second at least once");
      * </code></pre>
-     * 
+     *
      * See examples in javadoc for {@link Mockito} class
-     * 
+     *
      * @param mock to be verified
      * @param mode for example times(x) or atLeastOnce()
-     * 
+     *
      * @return mock object itself
      */
     <T> T verify(T mock, VerificationMode mode);
 
-    
+
     /**
-     * Verifies that no more interactions happened <b>in order</b>. 
+     * Verifies that no more interactions happened <b>in order</b>.
      * Different from {@link Mockito#verifyNoMoreInteractions(Object...)} because the order of verification matters.
      * <p>
      * Example:
@@ -73,18 +73,18 @@
      * mock.foo(); //1st
      * mock.bar(); //2nd
      * mock.baz(); //3rd
-     * 
+     *
      * InOrder inOrder = inOrder(mock);
-     * 
+     *
      * inOrder.verify(mock).bar(); //2n
      * inOrder.verify(mock).baz(); //3rd (last method)
-     * 
+     *
      * //passes because there are no more interactions after last method:
      * inOrder.verifyNoMoreInteractions();
-     * 
+     *
      * //however this fails because 1st method was not verified:
      * Mockito.verifyNoMoreInteractions(mock);
      * </code></pre>
      */
     void verifyNoMoreInteractions();
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/InjectMocks.java b/src/main/java/org/mockito/InjectMocks.java
index f1dbc7e..0430524 100644
--- a/src/main/java/org/mockito/InjectMocks.java
+++ b/src/main/java/org/mockito/InjectMocks.java
@@ -1,163 +1,165 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import java.lang.annotation.Documented;

-import java.lang.annotation.Retention;

-import java.lang.annotation.Target;

-

-import static java.lang.annotation.ElementType.FIELD;

-import static java.lang.annotation.RetentionPolicy.RUNTIME;

-

-/**

- * Mark a field on which injection should be performed.

- *

- * <ul>

- * <li>Allows shorthand mock and spy injection.</li>

- * <li>Minimizes repetitive mock and spy injection.</li>

- * </ul>

- * <p>

- * Mockito will try to inject mocks only either by constructor injection,

- * setter injection, or property injection in order and as described below.

- * If any of the following strategy fail, then Mockito <strong>won't report failure</strong>;

- * i.e. you will have to provide dependencies yourself.

- * <ol>

- *     <li><strong>Constructor injection</strong>; the biggest constructor is chosen,

- *     then arguments are resolved with mocks declared in the test only. If the object is successfully created

- *     with the constructor, then <strong>Mockito won't try the other strategies</strong>. Mockito has decided to no

- *     corrupt an object if it has a parametered constructor.

- *     <p><u>Note:</u> If arguments can not be found, then null is passed.

- *     If non-mockable types are wanted, then constructor injection won't happen.

- *     In these cases, you will have to satisfy dependencies yourself.</p></li>

- *

- *     <li><strong>Property setter injection</strong>; mocks will first be resolved by type (if a single type match

- *     injection will happen regardless of the name),

- *     then, if there is several property of the same type, by the match of the property name and the mock name.

- *     <p><u>Note 1:</u> If you have properties with the same type (or same erasure), it's better to name all &#064;Mock

- *     annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.</p>

- *     <p><u>Note 2:</u> If &#064;InjectMocks instance wasn't initialized before and have a no-arg constructor,

- *     then it will be initialized with this constructor.</p></li>

- *

- *     <li><strong>Field injection</strong>; mocks will first be resolved by type (if a single type match

- *     injection will happen regardless of the name),

- *     then, if there is several property of the same type, by the match of the field name and the mock name.

- *     <p><u>Note 1:</u> If you have fields with the same type (or same erasure), it's better to name all &#064;Mock

- *     annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.</p>

- *     <p><u>Note 2:</u> If &#064;InjectMocks instance wasn't initialized before and have a no-arg constructor,

- *     then it will be initialized with this constructor.</p></li>

- * </ol>

- * </p>

- *

- * <p>

- * Example:

- * <pre class="code"><code class="java">

- *   public class ArticleManagerTest extends SampleBaseTestCase {

- *

- *       &#064;Mock private ArticleCalculator calculator;

- *       &#064;Mock(name = "database") private ArticleDatabase dbMock; // note the mock name attribute

- *       &#064;Spy private UserProvider userProvider = new ConsumerUserProvider();

- *

- *       &#064;InjectMocks private ArticleManager manager;

- *

- *       &#064;Test public void shouldDoSomething() {

- *           manager.initiateArticle();

- *           verify(database).addListener(any(ArticleListener.class));

- *       }

- *   }

- *

- *   public class SampleBaseTestCase {

- *

- *       &#064;Before public void initMocks() {

- *           MockitoAnnotations.initMocks(this);

- *       }

- *   }

- * </code></pre>

- * </p>

- *

- * <p>

- * In the above example the field <code>ArticleManager</code> annotated with <code>&#064;InjectMocks</code> can have

- * a parameterized constructor only or a no-arg constructor only, or both.

- * All these constructors can be package protected, protected or private, however

- * <u>Mockito cannot instantiate inner classes, local classes, abstract classes and of course interfaces.</u>

- * <u>Beware of private nest static classes too.</u>

- *

- * <p>The same stands for setters or fields, they can be declared with private

- * visibility, Mockito will see them through reflection.

- * However fields that are static or final will be ignored.</p>

- *

- * <p>So on the field that needs injection, for example constructor injection will happen here :</p>

- * <pre class="code"><code class="java">

- *   public class ArticleManager {

- *       ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {

- *           // parameterized constructor

- *       }

- *   }

- * </code></pre>

- *

- * <p>Property setter injection will happen here :</p>

- * <pre class="code"><code class="java">

- *   public class ArticleManager {

- *       // no-arg constructor

- *       ArticleManager() {  }

- *

- *       // setter

- *       void setDatabase(ArticleDatabase database) { }

- *

- *       // setter

- *       void setCalculator(ArticleCalculator calculator) { }

- *   }

- * </code></pre>

- *

- * <p>Field injection will be used here :</p>

- * <pre class="code"><code class="java">

- *   public class ArticleManager {

- *       private ArticleDatabase database;

- *       private ArticleCalculator calculator;

- *   }

- * </code></pre>

- * </p>

- *

- * <p>And finally, no injection will happen on the type in this case:</p>

- * <pre class="code"><code class="java">

- *   public class ArticleManager {

- *       private ArticleDatabase database;

- *       private ArticleCalculator calculator;

- *

- *       ArticleManager(ArticleObserver observer, boolean flag) {

- *           // observer is not declared in the test above.

- *           // flag is not mockable anyway

- *       }

- *   }

- * </code></pre>

- * </p>

- *

- *

- * <p>

- * Again, note that &#064;InjectMocks will only inject mocks/spies created using the &#64;Spy or &#64;Mock annotation.

- * </p>

- *

- * <p>

- * <strong><code>MockitoAnnotations.initMocks(this)</code></strong> method has to be called to initialize annotated objects.

- * In above example, <code>initMocks()</code> is called in &#064;Before (JUnit4) method of test's base class.

- * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.

- * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (&#064;RunWith) or use the built-in

- * {@link org.mockito.runners.MockitoJUnitRunner}.

- * </p>

- *

- * <p>

- * Mockito is not an dependency injection framework, don't expect this shorthand utility to inject a complex graph of objects

- * be it mocks/spies or real objects.

- * </p>

- *

- * @see Mock

- * @see Spy

- * @see MockitoAnnotations#initMocks(Object)

- * @see org.mockito.runners.MockitoJUnitRunner

- * @since 1.8.3

- */

-@Documented

-@Target(FIELD)

-@Retention(RUNTIME)

-public @interface InjectMocks {}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Mark a field on which injection should be performed.
+ *
+ * <ul>
+ * <li>Allows shorthand mock and spy injection.</li>
+ * <li>Minimizes repetitive mock and spy injection.</li>
+ * </ul>
+ * <p>
+ * Mockito will try to inject mocks only either by constructor injection,
+ * setter injection, or property injection in order and as described below.
+ * If any of the following strategy fail, then Mockito <strong>won't report failure</strong>;
+ * i.e. you will have to provide dependencies yourself.
+ * <ol>
+ *     <li><strong>Constructor injection</strong>; the biggest constructor is chosen,
+ *     then arguments are resolved with mocks declared in the test only. If the object is successfully created
+ *     with the constructor, then <strong>Mockito won't try the other strategies</strong>. Mockito has decided to no
+ *     corrupt an object if it has a parametered constructor.
+ *     <p><u>Note:</u> If arguments can not be found, then null is passed.
+ *     If non-mockable types are wanted, then constructor injection won't happen.
+ *     In these cases, you will have to satisfy dependencies yourself.</p></li>
+ *
+ *     <li><strong>Property setter injection</strong>; mocks will first be resolved by type (if a single type match
+ *     injection will happen regardless of the name),
+ *     then, if there is several property of the same type, by the match of the property name and the mock name.
+ *     <p><u>Note 1:</u> If you have properties with the same type (or same erasure), it's better to name all &#064;Mock
+ *     annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.</p>
+ *     <p><u>Note 2:</u> If &#064;InjectMocks instance wasn't initialized before and have a no-arg constructor,
+ *     then it will be initialized with this constructor.</p></li>
+ *
+ *     <li><strong>Field injection</strong>; mocks will first be resolved by type (if a single type match
+ *     injection will happen regardless of the name),
+ *     then, if there is several property of the same type, by the match of the field name and the mock name.
+ *     <p><u>Note 1:</u> If you have fields with the same type (or same erasure), it's better to name all &#064;Mock
+ *     annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.</p>
+ *     <p><u>Note 2:</u> If &#064;InjectMocks instance wasn't initialized before and have a no-arg constructor,
+ *     then it will be initialized with this constructor.</p></li>
+ * </ol>
+ * </p>
+ *
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ *   public class ArticleManagerTest extends SampleBaseTestCase {
+ *
+ *       &#064;Mock private ArticleCalculator calculator;
+ *       &#064;Mock(name = "database") private ArticleDatabase dbMock; // note the mock name attribute
+ *       &#064;Spy private UserProvider userProvider = new ConsumerUserProvider();
+ *
+ *       &#064;InjectMocks private ArticleManager manager;
+ *
+ *       &#064;Test public void shouldDoSomething() {
+ *           manager.initiateArticle();
+ *           verify(database).addListener(any(ArticleListener.class));
+ *       }
+ *   }
+ *
+ *   public class SampleBaseTestCase {
+ *
+ *       &#064;Before public void initMocks() {
+ *           MockitoAnnotations.initMocks(this);
+ *       }
+ *   }
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * In the above example the field <code>ArticleManager</code> annotated with <code>&#064;InjectMocks</code> can have
+ * a parameterized constructor only or a no-arg constructor only, or both.
+ * All these constructors can be package protected, protected or private, however
+ * <u>Mockito cannot instantiate inner classes, local classes, abstract classes and of course interfaces.</u>
+ * <u>Beware of private nest static classes too.</u>
+ *
+ * <p>The same stands for setters or fields, they can be declared with private
+ * visibility, Mockito will see them through reflection.
+ * However fields that are static or final will be ignored.</p>
+ *
+ * <p>So on the field that needs injection, for example constructor injection will happen here :</p>
+ * <pre class="code"><code class="java">
+ *   public class ArticleManager {
+ *       ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {
+ *           // parameterized constructor
+ *       }
+ *   }
+ * </code></pre>
+ *
+ * <p>Property setter injection will happen here :</p>
+ * <pre class="code"><code class="java">
+ *   public class ArticleManager {
+ *       // no-arg constructor
+ *       ArticleManager() {  }
+ *
+ *       // setter
+ *       void setDatabase(ArticleDatabase database) { }
+ *
+ *       // setter
+ *       void setCalculator(ArticleCalculator calculator) { }
+ *   }
+ * </code></pre>
+ *
+ * <p>Field injection will be used here :</p>
+ * <pre class="code"><code class="java">
+ *   public class ArticleManager {
+ *       private ArticleDatabase database;
+ *       private ArticleCalculator calculator;
+ *   }
+ * </code></pre>
+ * </p>
+ *
+ * <p>And finally, no injection will happen on the type in this case:</p>
+ * <pre class="code"><code class="java">
+ *   public class ArticleManager {
+ *       private ArticleDatabase database;
+ *       private ArticleCalculator calculator;
+ *
+ *       ArticleManager(ArticleObserver observer, boolean flag) {
+ *           // observer is not declared in the test above.
+ *           // flag is not mockable anyway
+ *       }
+ *   }
+ * </code></pre>
+ * </p>
+ *
+ *
+ * <p>
+ * Again, note that &#064;InjectMocks will only inject mocks/spies created using the &#64;Spy or &#64;Mock annotation.
+ * </p>
+ *
+ * <p>
+ * <strong><code>MockitoAnnotations.initMocks(this)</code></strong> method has to be called to initialize annotated objects.
+ * In above example, <code>initMocks()</code> is called in &#064;Before (JUnit4) method of test's base class.
+ * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.
+ * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (&#064;RunWith) or use the built-in
+ * {@link MockitoJUnitRunner}.
+ * </p>
+ *
+ * <p>
+ * Mockito is not an dependency injection framework, don't expect this shorthand utility to inject a complex graph of objects
+ * be it mocks/spies or real objects.
+ * </p>
+ *
+ * @see Mock
+ * @see Spy
+ * @see MockitoAnnotations#initMocks(Object)
+ * @see MockitoJUnitRunner
+ * @since 1.8.3
+ */
+@Documented
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface InjectMocks {}
diff --git a/src/main/java/org/mockito/Matchers.java b/src/main/java/org/mockito/Matchers.java
index 971452e..f6d07bc 100644
--- a/src/main/java/org/mockito/Matchers.java
+++ b/src/main/java/org/mockito/Matchers.java
@@ -1,880 +1,13 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import org.hamcrest.Matcher;

-import org.mockito.internal.matchers.*;

-import org.mockito.internal.matchers.apachecommons.ReflectionEquals;

-import org.mockito.internal.progress.HandyReturnValues;

-import org.mockito.internal.progress.MockingProgress;

-import org.mockito.internal.progress.ThreadSafeMockingProgress;

-

-import java.util.Collection;

-import java.util.List;

-import java.util.Map;

-import java.util.Set;

-

-/**

- * Allow flexible verification or stubbing. See also {@link AdditionalMatchers}.

- * <p>

- * {@link Mockito} extends Matchers so to get access to all matchers just import Mockito class statically.

- * <pre class="code"><code class="java">

- *  //stubbing using anyInt() argument matcher

- *  when(mockedList.get(anyInt())).thenReturn("element");

- *  

- *  //following prints "element"

- *  System.out.println(mockedList.get(999));

- *  

- *  //you can also verify using argument matcher

- *  verify(mockedList).get(anyInt());

- * </code></pre>

- * Scroll down to see all methods - full list of matchers.

- * <p>

- * <b>Warning:</b>

- * <p>

- * If you are using argument matchers, <b>all arguments</b> have to be provided by matchers.

- * <p>

- * E.g: (example shows verification but the same applies to stubbing):

- * <pre class="code"><code class="java">

- *   verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);

- *   //above is correct - eq() is also an argument matcher

- *   

- *   verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);

- *   //above is incorrect - exception will be thrown because third argument is given without argument matcher.

- * </code></pre>

- * <p>

- * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.

- * Internally, they record a matcher on a stack and return a dummy value (usually null).

- * This implementation is due static type safety imposed by java compiler.

- * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.

- *

- * <p>

- * <b>Warning 2:</b>

- * <p>

- * The any family methods <b>*doesn't do any type checks*</b>, those are only here to avoid casting

- * in your code. If you want to perform type checks use the {@link #isA(Class)} method.

- * This <b>might</b> however change (type checks could be added) in a future major release.

- *

- * <h1>Custom Argument Matchers</h1>

- * 

- * Use {@link Matchers#argThat} method and pass an instance of hamcrest {@link Matcher}.

- * <p>

- * Before you start implementing your own custom argument matcher, make sure you check out {@link ArgumentCaptor} api.

- * <p>

- * So, how to implement your own argument matcher?

- * First, you might want to subclass {@link ArgumentMatcher} which is an hamcrest matcher with predefined describeTo() method.

- * Default description generated by describeTo() uses <b>decamelized class name</b> - to promote meaningful class names.

- * <p>

- * Example:

- * 

- * <pre class="code"><code class="java">

- *   class IsListOfTwoElements extends ArgumentMatcher&lt;List&gt; {

- *      public boolean matches(Object list) {

- *          return ((List) list).size() == 2;

- *      }

- *   }

- *   

- *   List mock = mock(List.class);

- *   

- *   when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);

- *   

- *   mock.addAll(Arrays.asList("one", "two"));

- *   

- *   verify(mock).addAll(argThat(new IsListOfTwoElements()));

- * </code></pre>

- * 

- * To keep it readable you may want to extract method, e.g:

- * <pre class="code"><code class="java">

- *   verify(mock).addAll(<b>argThat(new IsListOfTwoElements())</b>);

- *   //becomes

- *   verify(mock).addAll(<b>listOfTwoElements()</b>);

- * </code></pre>

- *

- * <b>Warning:</b> Be reasonable with using complicated argument matching, especially custom argument matchers, as it can make the test less readable. 

- * Sometimes it's better to implement equals() for arguments that are passed to mocks 

- * (Mockito naturally uses equals() for argument matching). 

- * This can make the test cleaner. 

- * <p>

- * Also, <b>sometimes {@link ArgumentCaptor} may be a better fit</b> than custom matcher. 

- * For example, if custom argument matcher is not likely to be reused

- * or you just need it to assert on argument values to complete verification of behavior.

- */

-@SuppressWarnings("unchecked")

-public class Matchers {

-    

-    private static final MockingProgress MOCKING_PROGRESS = new ThreadSafeMockingProgress();

-

-    /**

-     * Any <code>boolean</code>, <code>Boolean</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>false</code>.

-     */

-    public static boolean anyBoolean() {

-        return reportMatcher(Any.ANY).returnFalse();

-    }

-

-    /**

-     * Any <code>byte</code>, <code>Byte</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static byte anyByte() {

-        return reportMatcher(Any.ANY).returnZero();

-    }

-

-    /**

-     * Any <code>char</code>, <code>Character</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static char anyChar() {

-        return reportMatcher(Any.ANY).returnChar();

-    }

-

-    /**

-     * Any int, Integer or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static int anyInt() {

-        return reportMatcher(Any.ANY).returnZero();

-    }

-

-    /**

-     * Any <code>long</code>, <code>Long</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static long anyLong() {

-        return reportMatcher(Any.ANY).returnZero();

-    }

-

-    /**

-     * Any <code>float</code>, <code>Float</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static float anyFloat() {

-        return reportMatcher(Any.ANY).returnZero();

-    }

-

-    /**

-     * Any <code>double</code>, <code>Double</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static double anyDouble() {

-        return reportMatcher(Any.ANY).returnZero();

-    }

-

-    /**

-     * Any <code>short</code>, <code>Short</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>0</code>.

-     */

-    public static short anyShort() {

-        return reportMatcher(Any.ANY).returnZero();

-    }

-

-    /**

-     * Any <code>Object</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * Has aliases: {@link #any()} and {@link #any(Class clazz)}

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>null</code>.

-     */

-    public static <T> T anyObject() {

-        return (T) reportMatcher(Any.ANY).returnNull();

-    }

-

-    /**

-     * Any vararg, meaning any number and values of arguments.

-     * <p>

-     * Example:

-     * <pre class="code"><code class="java">

-     *   //verification:

-     *   mock.foo(1, 2);

-     *   mock.foo(1, 2, 3, 4);

-     *

-     *   verify(mock, times(2)).foo(anyVararg());

-     *

-     *   //stubbing:

-     *   when(mock.foo(anyVararg()).thenReturn(100);

-     *

-     *   //prints 100

-     *   System.out.println(mock.foo(1, 2));

-     *   //also prints 100

-     *   System.out.println(mock.foo(1, 2, 3, 4));

-     * </code></pre>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @return <code>null</code>.

-     */

-    public static <T> T anyVararg() {

-        return (T) reportMatcher(AnyVararg.ANY_VARARG).returnNull();

-    }

-    

-    /**

-     * Any kind object, not necessary of the given class.

-     * The class argument is provided only to avoid casting.

-     * <p>

-     * Sometimes looks better than <code>anyObject()</code> - especially when explicit casting is required

-     * <p>

-     * Alias to {@link Matchers#anyObject()}

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param clazz The type to avoid casting

-     * @return <code>null</code>.

-     */

-    public static <T> T any(Class<T> clazz) {

-        return (T) reportMatcher(Any.ANY).returnFor(clazz);

-    }

-    

-    /**

-     * Any object or <code>null</code>.

-     * <p>

-     * Shorter alias to {@link Matchers#anyObject()}

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>null</code>.

-     */

-    public static <T> T any() {

-        return (T) anyObject();

-    }

-

-    /**

-     * Any <code>String</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return empty String ("")

-     */

-    public static String anyString() {

-        return reportMatcher(Any.ANY).returnString();

-    }

-    

-    /**

-     * Any <code>List</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return empty List.

-     */

-    public static List anyList() {

-        return reportMatcher(Any.ANY).returnList();

-    }    

-    

-    /**

-     * Generic friendly alias to {@link Matchers#anyList()}.

-     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.

-     * <p>

-     * Any <code>List</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param clazz Type owned by the list to avoid casting

-     * @return empty List.

-     */

-    public static <T> List<T> anyListOf(Class<T> clazz) {

-        return (List) reportMatcher(Any.ANY).returnList();

-    }    

-    

-    /**

-     * Any <code>Set</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @return empty Set

-     */

-    public static Set anySet() {

-        return reportMatcher(Any.ANY).returnSet();

-    }

-    

-    /**

-     * Generic friendly alias to {@link Matchers#anySet()}.

-     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.

-     * <p>

-     * Any <code>Set</code> or <code>null</code>

-     * <p>

-     * This method <b>*dones't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @param clazz Type owned by the Set to avoid casting

-     * @return empty Set

-     */

-    public static <T> Set<T> anySetOf(Class<T> clazz) {

-        return (Set) reportMatcher(Any.ANY).returnSet();

-    }

-

-    /**

-     * Any <code>Map</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return empty Map.

-     */

-    public static Map anyMap() {

-        return reportMatcher(Any.ANY).returnMap();

-    }

-

-    /**

-     * Generic friendly alias to {@link Matchers#anyMap()}.

-     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.

-     * <p>

-     * Any <code>Map</code> or <code>null</code>

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @param keyClazz Type of the map key to avoid casting

-     * @param valueClazz Type of the value to avoid casting

-     * @return empty Map.

-     */

-    public static <K, V>  Map<K, V> anyMapOf(Class<K> keyClazz, Class<V> valueClazz) {

-        return reportMatcher(Any.ANY).returnMap();

-    }

-    

-    /**

-     * Any <code>Collection</code> or <code>null</code>.

-     * <p>

-     * This method <b>*dones't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return empty Collection.

-     */

-    public static Collection anyCollection() {

-        return reportMatcher(Any.ANY).returnList();

-    }    

-    

-    /**

-     * Generic friendly alias to {@link Matchers#anyCollection()}.

-     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.     

-     * <p>

-     * Any <code>Collection</code> or <code>null</code>.

-     * <p>

-     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting

-     * in your code. This might however change (type checks could be added) in a

-     * future major release.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param clazz Type owned by the collection to avoid casting

-     * @return empty Collection.

-     */

-    public static <T> Collection<T> anyCollectionOf(Class<T> clazz) {

-        return (Collection) reportMatcher(Any.ANY).returnList();

-    }    

-

-    /**

-     * <code>Object</code> argument that implements the given class.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param <T>

-     *            the accepted type.

-     * @param clazz

-     *            the class of the accepted type.

-     * @return <code>null</code>.

-     */

-    public static <T> T isA(Class<T> clazz) {

-        return reportMatcher(new InstanceOf(clazz)).<T>returnFor(clazz);

-    }

-

-    /**

-     * <code>boolean</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static boolean eq(boolean value) {

-        return reportMatcher(new Equals(value)).returnFalse();

-    }

-

-    /**

-     * <code>byte</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static byte eq(byte value) {

-        return reportMatcher(new Equals(value)).returnZero();

-    }

-

-    /**

-     * <code>char</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static char eq(char value) {

-        return reportMatcher(new Equals(value)).returnChar();

-    }

-

-    /**

-     * <code>double</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static double eq(double value) {

-        return reportMatcher(new Equals(value)).returnZero();

-    }

-

-    /**

-     * <code>float</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static float eq(float value) {

-        return reportMatcher(new Equals(value)).returnZero();

-    }

-    

-    /**

-     * <code>int</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static int eq(int value) {

-        return reportMatcher(new Equals(value)).returnZero();

-    }

-

-    /**

-     * <code>long</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static long eq(long value) {

-        return reportMatcher(new Equals(value)).returnZero();

-    }

-

-    /**

-     * <code>short</code> argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>0</code>.

-     */

-    public static short eq(short value) {

-        return reportMatcher(new Equals(value)).returnZero();

-    }

-

-    /**

-     * Object argument that is equal to the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @return <code>null</code>.

-     */

-    public static <T> T eq(T value) {

-        return (T) reportMatcher(new Equals(value)).<T>returnFor(value);

-    }

-

-    /**

-     * Object argument that is reflection-equal to the given value with support for excluding

-     * selected fields from a class.

-     * <p>

-     * This matcher can be used when equals() is not implemented on compared objects.

-     * Matcher uses java reflection API to compare fields of wanted and actual object.

-     * <p>

-     * Works similarly to EqualsBuilder.reflectionEquals(this, other, exlucdeFields) from

-     * apache commons library.

-     * <p>

-     * <b>Warning</b> The equality check is shallow!

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param value

-     *            the given value.

-     * @param excludeFields

-     *            fields to exclude, if field does not exist it is ignored.

-     * @return <code>null</code>.

-     */

-    public static <T> T refEq(T value, String... excludeFields) {

-        return reportMatcher(new ReflectionEquals(value, excludeFields)).<T>returnNull();

-    }

-    

-    /**

-     * Object argument that is the same as the given value.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param <T>

-     *            the type of the object, it is passed through to prevent casts.

-     * @param value

-     *            the given value.

-     * @return <code>null</code>.

-     */

-    public static <T> T same(T value) {

-        return (T) reportMatcher(new Same(value)).<T>returnFor(value);

-    }

-

-    /**

-     * <code>null</code> argument.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>null</code>.

-     */

-    public static Object isNull() {

-        return reportMatcher(Null.NULL).returnNull();

-    }

-

-    /**

-     * <code>null</code> argument.

-     * The class argument is provided to avoid casting.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @param clazz Type to avoid casting

-     * @return <code>null</code>.

-     */

-    public static <T> T isNull(Class<T> clazz) {

-        return (T) reportMatcher(Null.NULL).returnNull();

-    }

-

-    /**

-     * Not <code>null</code> argument.

-     * <p>

-     * alias to {@link Matchers#isNotNull()}

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>null</code>.

-     */

-    public static Object notNull() {

-        return reportMatcher(NotNull.NOT_NULL).returnNull();

-    }

-

-    /**

-     * Not <code>null</code> argument, not necessary of the given class.

-     * The class argument is provided to avoid casting.

-     * <p>

-     * alias to {@link Matchers#isNotNull(Class)}

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @param clazz Type to avoid casting

-     * @return <code>null</code>.

-     */

-    public static <T> T notNull(Class<T> clazz) {

-        return (T) reportMatcher(NotNull.NOT_NULL).returnNull();

-    }

-    

-    /**

-     * Not <code>null</code> argument.

-     * <p>

-     * alias to {@link Matchers#notNull()}

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @return <code>null</code>.

-     */

-    public static Object isNotNull() {

-        return notNull();

-    }

-

-    /**

-     * Not <code>null</code> argument, not necessary of the given class.

-     * The class argument is provided to avoid casting.

-     * <p>

-     * alias to {@link Matchers#notNull(Class)}

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     *

-     * @param clazz Type to avoid casting

-     * @return <code>null</code>.

-     */

-    public static <T> T isNotNull(Class<T> clazz) {

-        return notNull(clazz);

-    }

-

-    /**

-     * <code>String</code> argument that contains the given substring.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param substring

-     *            the substring.

-     * @return empty String ("").

-     */

-    public static String contains(String substring) {

-        return reportMatcher(new Contains(substring)).returnString();

-    }

-

-    /**

-     * <code>String</code> argument that matches the given regular expression.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param regex

-     *            the regular expression.

-     * @return empty String ("").

-     */

-    public static String matches(String regex) {

-        return reportMatcher(new Matches(regex)).returnString();

-    }

-

-    /**

-     * <code>String</code> argument that ends with the given suffix.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param suffix

-     *            the suffix.

-     * @return empty String ("").

-     */

-    public static String endsWith(String suffix) {

-        return reportMatcher(new EndsWith(suffix)).returnString();

-    }

-

-    /**

-     * <code>String</code> argument that starts with the given prefix.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param prefix

-     *            the prefix.

-     * @return empty String ("").

-     */

-    public static String startsWith(String prefix) {

-        return reportMatcher(new StartsWith(prefix)).returnString();

-    }

-

-    /**

-     * Allows creating custom argument matchers.

-     * <p>

-     * In rare cases when the parameter is a primitive then you <b>*must*</b> use relevant intThat(), floatThat(), etc. method.

-     * This way you will avoid <code>NullPointerException</code> during auto-unboxing.

-     * <p>

-     * See examples in javadoc for {@link ArgumentMatcher} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>null</code>.

-     */

-    public static <T> T argThat(Matcher<T> matcher) {

-        return reportMatcher(matcher).<T>returnNull();

-    }

-    

-    /**

-     * Allows creating custom <code>Character</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static char charThat(Matcher<Character> matcher) {

-        return reportMatcher(matcher).returnChar();

-    }

-    

-    /**

-     * Allows creating custom <code>Boolean</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>false</code>.

-     */

-    public static boolean booleanThat(Matcher<Boolean> matcher) {

-        return reportMatcher(matcher).returnFalse();

-    }

-    

-    /**

-     * Allows creating custom <code>Byte</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static byte byteThat(Matcher<Byte> matcher) {

-        return reportMatcher(matcher).returnZero();

-    }

-    

-    /**

-     * Allows creating custom <code>Short</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static short shortThat(Matcher<Short> matcher) {

-        return reportMatcher(matcher).returnZero();

-    }

-    

-    /**

-     * Allows creating custom <code>Integer</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static int intThat(Matcher<Integer> matcher) {

-        return reportMatcher(matcher).returnZero();

-    }

-

-    /**

-     * Allows creating custom <code>Long</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static long longThat(Matcher<Long> matcher) {

-        return reportMatcher(matcher).returnZero();

-    }

-    

-    /**

-     * Allows creating custom <code>Float</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static float floatThat(Matcher<Float> matcher) {

-        return reportMatcher(matcher).returnZero();

-    }

-    

-    /**

-     * Allows creating custom <code>Double</code> argument matchers.

-     * <p>

-     * See examples in javadoc for {@link Matchers} class

-     * 

-     * @param matcher decides whether argument matches

-     * @return <code>0</code>.

-     */

-    public static double doubleThat(Matcher<Double> matcher) {

-        return reportMatcher(matcher).returnZero();

-    }

-

-    private static HandyReturnValues reportMatcher(Matcher<?> matcher) {

-        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportMatcher(matcher);

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+/**
+ * @deprecated Use {@link ArgumentMatchers}. This class is now deprecated in order to avoid a name clash with Hamcrest
+ * <code>org.hamcrest.Matchers</code> class. This class will likely be removed in version 3.0.
+ */
+@Deprecated
+public class Matchers extends ArgumentMatchers {
+}
diff --git a/src/main/java/org/mockito/Mock.java b/src/main/java/org/mockito/Mock.java
index baf1c25..749578b 100644
--- a/src/main/java/org/mockito/Mock.java
+++ b/src/main/java/org/mockito/Mock.java
@@ -2,72 +2,75 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito;

-

-import java.lang.annotation.Documented;

-import java.lang.annotation.Retention;

-import java.lang.annotation.Target;

-

-import static java.lang.annotation.ElementType.FIELD;

-import static java.lang.annotation.RetentionPolicy.RUNTIME;

-

-/**

- * Mark a field as a mock.

- *

- * <ul>

- * <li>Allows shorthand mock creation.</li>

- * <li>Minimizes repetitive mock creation code.</li>

- * <li>Makes the test class more readable.</li>

- * <li>Makes the verification error easier to read because the <b>field name</b> is used to identify the mock.</li>

- * </ul>

- *

- * <pre class="code"><code class="java">

- *   public class ArticleManagerTest extends SampleBaseTestCase {

- *

- *       &#064;Mock private ArticleCalculator calculator;

- *       &#064;Mock(name = "database") private ArticleDatabase dbMock;

- *       &#064;Mock(answer = RETURNS_MOCKS) private UserProvider userProvider;

- *       &#064;Mock(extraInterfaces = {Queue.class, Observer.class}) private  articleMonitor;

- *

- *       private ArticleManager manager;

- *

- *       &#064;Before public void setup() {

- *           manager = new ArticleManager(userProvider, database, calculator, articleMonitor);

- *       }

- *   }

- *

- *   public class SampleBaseTestCase {

- *

- *       &#064;Before public void initMocks() {

- *           MockitoAnnotations.initMocks(this);

- *       }

- *   }

- * </code></pre>

- *

- * <p>

- * <strong><code>MockitoAnnotations.initMocks(this)</code></strong> method has to be called to initialize annotated objects.

- * In above example, <code>initMocks()</code> is called in &#064;Before (JUnit4) method of test's base class.

- * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.

- * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (&#064;RunWith) or use the built-in

- * {@link org.mockito.runners.MockitoJUnitRunner}.

- * </p>

- *

- * @see Mockito#mock(Class)

- * @see Spy

- * @see InjectMocks

- * @see MockitoAnnotations#initMocks(Object)

- * @see org.mockito.runners.MockitoJUnitRunner

- */

-@Target(FIELD)

-@Retention(RUNTIME)

-@Documented

-public @interface Mock {

-

-    Answers answer() default Answers.RETURNS_DEFAULTS;

-

-    String name() default "";

-

+package org.mockito;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Mark a field as a mock.
+ *
+ * <ul>
+ * <li>Allows shorthand mock creation.</li>
+ * <li>Minimizes repetitive mock creation code.</li>
+ * <li>Makes the test class more readable.</li>
+ * <li>Makes the verification error easier to read because the <b>field name</b> is used to identify the mock.</li>
+ * </ul>
+ *
+ * <pre class="code"><code class="java">
+ *   public class ArticleManagerTest extends SampleBaseTestCase {
+ *
+ *       &#064;Mock private ArticleCalculator calculator;
+ *       &#064;Mock(name = "database") private ArticleDatabase dbMock;
+ *       &#064;Mock(answer = RETURNS_MOCKS) private UserProvider userProvider;
+ *       &#064;Mock(extraInterfaces = {Queue.class, Observer.class}) private  articleMonitor;
+ *
+ *       private ArticleManager manager;
+ *
+ *       &#064;Before public void setup() {
+ *           manager = new ArticleManager(userProvider, database, calculator, articleMonitor);
+ *       }
+ *   }
+ *
+ *   public class SampleBaseTestCase {
+ *
+ *       &#064;Before public void initMocks() {
+ *           MockitoAnnotations.initMocks(this);
+ *       }
+ *   }
+ * </code></pre>
+ *
+ * <p>
+ * <strong><code>MockitoAnnotations.initMocks(this)</code></strong> method has to be called to initialize annotated objects.
+ * In above example, <code>initMocks()</code> is called in &#064;Before (JUnit4) method of test's base class.
+ * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.
+ * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (&#064;RunWith) or use the built-in
+ * {@link MockitoJUnitRunner}.
+ * </p>
+ *
+ * @see Mockito#mock(Class)
+ * @see Spy
+ * @see InjectMocks
+ * @see MockitoAnnotations#initMocks(Object)
+ * @see MockitoJUnitRunner
+ */
+@Target({FIELD, PARAMETER})
+@Retention(RUNTIME)
+@Documented
+public @interface Mock {
+
+    Answers answer() default Answers.RETURNS_DEFAULTS;
+
+    String name() default "";
+
     Class<?>[] extraInterfaces() default {};
-    
-    boolean serializable() default false;

-}

+
+    boolean serializable() default false;
+}
diff --git a/src/main/java/org/mockito/MockSettings.java b/src/main/java/org/mockito/MockSettings.java
index 2b5f934..137764c 100644
--- a/src/main/java/org/mockito/MockSettings.java
+++ b/src/main/java/org/mockito/MockSettings.java
@@ -40,7 +40,6 @@
 
     /**
      * Specifies extra interfaces the mock should implement. Might be useful for legacy code or some corner cases.
-     * For background, see issue 51 <a href="http://code.google.com/p/mockito/issues/detail?id=51">here</a>
      * <p>
      * This mysterious feature should be used very occasionally.
      * The object under test should know exactly its collaborators & dependencies.
diff --git a/src/main/java/org/mockito/MockingDetails.java b/src/main/java/org/mockito/MockingDetails.java
index 46099b5..9038b62 100644
--- a/src/main/java/org/mockito/MockingDetails.java
+++ b/src/main/java/org/mockito/MockingDetails.java
@@ -1,43 +1,111 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import org.mockito.invocation.Invocation;

-

-import java.util.Collection;

-

-/**

- * Provides mocking information.

- * For example, you can identify whether a particular object is either a mock or a spy.

- *

- * @since 1.9.5

- */

-public interface MockingDetails {

-    

-    /**

-     * Informs if the object is a mock. isMock() for null input returns false.

-     * @return true if the object is a mock or a spy.

-     *

-     * @since 1.9.5

-     */

-    boolean isMock();

-

-    /**

-     * Informs if the object is a spy. isSpy() for null input returns false.

-     * @return true if the object is a spy.

-     *

-     * @since 1.9.5

-     */

-    boolean isSpy();

-    

-    /**

-     * Provides a collection of methods indicating the invocations of the object

-     * @return collection of Invocation representing the invocations 

-     * for the object.

-     *

-     * @since 1.10.0

-     */

-    Collection<Invocation> getInvocations();

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.stubbing.Stubbing;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.quality.MockitoHint;
+
+import java.util.Collection;
+
+/**
+ * Provides mocking information.
+ * For example, you can identify whether a particular object is either a mock or a spy.
+ * For examples and more information please refer to the javadoc of the individual methods on this class.
+ *
+ * @since 1.9.5
+ */
+public interface MockingDetails {
+
+    /**
+     * Informs if the object is a mock. isMock() for null input returns false.
+     * @return true if the object is a mock or a spy (spy is a different kind of mock, but it is still a mock).
+     *
+     * @since 1.9.5
+     */
+    boolean isMock();
+
+    /**
+     * Informs if the object is a spy. isSpy() for null input returns false.
+     * @return true if the object is a spy.
+     *
+     * @since 1.9.5
+     */
+    boolean isSpy();
+
+    /**
+     * All method invocations on this mock.
+     * Can be empty - it means there were no interactions with the mock.
+     * <p>
+     * This method is useful for framework integrators and for certain edge cases.
+     * <p>
+     * Manipulating the collection (e.g. by removing, adding elements) is safe and has no effect on the mock.
+     * <p>
+     * Throws meaningful exception when object wrapped by MockingDetails is not a mock.
+     *
+     * @since 1.10.0
+     */
+    Collection<Invocation> getInvocations();
+
+    /**
+     * Returns various mock settings provided when the mock was created, for example:
+     *  mocked class, mock name (if any), any extra interfaces (if any), etc.
+     * See also {@link MockCreationSettings}.
+     * <p>
+     * This method is useful for framework integrators and for certain edge cases.
+     * <p>
+     * If <code>null</code> or non-mock was passed to {@link Mockito#mockingDetails(Object)}
+     * then this method will throw with an appropriate exception.
+     * After all, non-mock objects do not have any mock creation settings.
+     * @since 2.1.0
+     */
+    MockCreationSettings<?> getMockCreationSettings();
+
+    /**
+     * Returns stubbings declared on this mock object.
+     * <pre class="code"><code class="java">
+     *   Mockito.mockingDetails(mock).getStubbings()
+     * </code></pre>
+     * What is 'stubbing'?
+     * Stubbing is your when(x).then(y) declaration, e.g. configuring the mock to behave in a specific way,
+     * when specific method with specific arguments is invoked on a mock.
+     * Typically stubbing is configuring mock to return X when method Y is invoked.
+     * <p>
+     * Why do you need to access stubbings of a mock?
+     * In a normal workflow of creation clean tests, there is no need for this API.
+     * However, it is useful for advanced users, edge cases or framework integrators.
+     * For example, Mockito internally uses this API to report and detect unused stubbings
+     * that should be removed from test. Unused stubbings are dead code that needs to be removed
+     * (see {@link MockitoHint}).
+     * <p>
+     * Manipulating the collection (e.g. by removing, adding elements) is safe and has no effect on the mock.
+     * <p>
+     * This method throws meaningful exception when object wrapped by MockingDetails is not a mock.
+     *
+     * @since 2.2.3
+     */
+    Collection<Stubbing> getStubbings();
+
+    /**
+     * Returns printing-friendly list of the invocations that occurred with the mock object.
+     * Additionally, this method prints stubbing information, including unused stubbings.
+     * For more information about unused stubbing detection see {@link MockitoHint}.
+     * <p>
+     * You can use this method for debugging,
+     *  print the output of this method to the console to find out about all interactions with the mock.
+     * <p>
+     * Content that is printed is subject to change as we discover better ways of presenting important mock information.
+     * Don't write code that depends on the output of this method.
+     * If you need to know about interactions and stubbings, use {@link #getStubbings()} and {@link #getInvocations()}.
+     * <p>
+     * This method was moved from the deprecated and semi-hidden type {@link MockitoDebugger}.
+     * <p>
+     * This method throws meaningful exception when object wrapped by MockingDetails is not a mock.
+     *
+     * @since 2.2.6
+     */
+    String printInvocations();
+}
diff --git a/src/main/java/org/mockito/Mockito.java b/src/main/java/org/mockito/Mockito.java
index 4c03cc0..8db7304 100644
--- a/src/main/java/org/mockito/Mockito.java
+++ b/src/main/java/org/mockito/Mockito.java
@@ -1,2297 +1,2757 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import org.mockito.internal.MockitoCore;

-import org.mockito.internal.creation.MockSettingsImpl;

-import org.mockito.internal.debugging.MockitoDebuggerImpl;

-import org.mockito.internal.stubbing.answers.*;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsMoreEmptyValues;

-import org.mockito.internal.verification.VerificationModeFactory;

-import org.mockito.runners.MockitoJUnitRunner;

-import org.mockito.stubbing.*;

-import org.mockito.verification.*;

-import org.mockito.junit.*;

-

-/**

- * <p align="left"><img src="logo.jpg"/></p>

- * Mockito library enables mocks creation, verification and stubbing.

- * <p>

- * This javadoc content is also available on the <a href="http://mockito.org">http://mockito.org</a> web page.

- * All documentation is kept in javadocs because it guarantees consistency between what's on the web and what's in the source code.

- * Also, it makes possible to access documentation straight from the IDE even if you work offline.

- *

- * <h1>Contents</h1>

- *

- * <b>

- *      <a href="#1">1. Let's verify some behaviour! </a><br/>

- *      <a href="#2">2. How about some stubbing? </a><br/>

- *      <a href="#3">3. Argument matchers </a><br/>

- *      <a href="#4">4. Verifying exact number of invocations / at least once / never </a><br/>

- *      <a href="#5">5. Stubbing void methods with exceptions </a><br/>

- *      <a href="#6">6. Verification in order </a><br/>

- *      <a href="#7">7. Making sure interaction(s) never happened on mock </a><br/>

- *      <a href="#8">8. Finding redundant invocations </a><br/>

- *      <a href="#9">9. Shorthand for mocks creation - <code>&#064;Mock</code> annotation </a><br/>

- *      <a href="#10">10. Stubbing consecutive calls (iterator-style stubbing) </a><br/>

- *      <a href="#11">11. Stubbing with callbacks </a><br/>

- *      <a href="#12">12. <code>doReturn()</code>|<code>doThrow()</code>|<code>doAnswer()</code>|<code>doNothing()</code>|<code>doCallRealMethod()</code> family of methods</a><br/>

- *      <a href="#13">13. Spying on real objects </a><br/>

- *      <a href="#14">14. Changing default return values of unstubbed invocations (Since 1.7) </a><br/>

- *      <a href="#15">15. Capturing arguments for further assertions (Since 1.8.0) </a><br/>

- *      <a href="#16">16. Real partial mocks (Since 1.8.0) </a><br/>

- *      <a href="#17">17. Resetting mocks (Since 1.8.0) </a><br/>

- *      <a href="#18">18. Troubleshooting & validating framework usage (Since 1.8.0) </a><br/>

- *      <a href="#19">19. Aliases for behavior driven development (Since 1.8.0) </a><br/>

- *      <a href="#20">20. Serializable mocks (Since 1.8.1) </a><br/>

- *      <a href="#21">21. New annotations: <code>&#064;Captor</code>, <code>&#064;Spy</code>, <code>&#064;InjectMocks</code> (Since 1.8.3) </a><br/>

- *      <a href="#22">22. Verification with timeout (Since 1.8.5) </a><br/>

- *      <a href="#23">23. Automatic instantiation of <code>&#064;Spies</code>, <code>&#064;InjectMocks</code> and constructor injection goodness (Since 1.9.0)</a><br/>

- *      <a href="#24">24. One-liner stubs (Since 1.9.0)</a><br/>

- *      <a href="#25">25. Verification ignoring stubs (Since 1.9.0)</a><br/>

- *      <a href="#26">26. Mocking details (Since 1.9.5)</a><br/>

- *      <a href="#27">27. Delegate calls to real instance (Since 1.9.5)</a><br/>

- *      <a href="#28">28. <code>MockMaker</code> API (Since 1.9.5)</a><br/>

- *      <a href="#29">29. (new) BDD style verification (Since 1.10.0)</a><br/>

- *      <a href="#30">30. (new) Spying or mocking abstract classes (Since 1.10.12)</a><br/>

- * </b>

- *

- * <p>

- * Following examples mock a List, because everyone knows its interface (methods

- * like <code>add()</code>, <code>get()</code>, <code>clear()</code> will be used). <br>

- * You probably wouldn't mock List class 'in real'.

- *

- *

- *

- *

- * <h3 id="1">1. <a class="meaningful_link" href="#verification">Let's verify some behaviour!</a></h3>

- *

- * <pre class="code"><code class="java">

- * //Let's import Mockito statically so that the code looks clearer

- * import static org.mockito.Mockito.*;

- *

- * //mock creation

- * List mockedList = mock(List.class);

- *

- * //using mock object

- * mockedList.add("one");

- * mockedList.clear();

- *

- * //verification

- * verify(mockedList).add("one");

- * verify(mockedList).clear();

- * </code></pre>

- *

- * <p>

- * Once created, mock will remember all interactions. Then you can selectively

- * verify whatever interaction you are interested in.

- *

- *

- *

- *

- * <h3 id="2">2. <a class="meaningful_link" href="#stubbing">How about some stubbing?</a></h3>

- *

- * <pre class="code"><code class="java">

- * //You can mock concrete classes, not only interfaces

- * LinkedList mockedList = mock(LinkedList.class);

- *

- * //stubbing

- * when(mockedList.get(0)).thenReturn("first");

- * when(mockedList.get(1)).thenThrow(new RuntimeException());

- *

- * //following prints "first"

- * System.out.println(mockedList.get(0));

- *

- * //following throws runtime exception

- * System.out.println(mockedList.get(1));

- *

- * //following prints "null" because get(999) was not stubbed

- * System.out.println(mockedList.get(999));

- *

- * //Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>

- * //If your code cares what get(0) returns then something else breaks (often before even verify() gets executed).

- * //If your code doesn't care what get(0) returns then it should not be stubbed. Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.

- * verify(mockedList).get(0);

- * </code></pre>

- *

- * <ul>

- * <li> By default, for all methods that return value, mock returns null, an

- * empty collection or appropriate primitive/primitive wrapper value (e.g: 0,

- * false, ... for int/Integer, boolean/Boolean, ...). </li>

- *

- * <li> Stubbing can be overridden: for example common stubbing can go to

- * fixture setup but the test methods can override it.

- * Please note that overridding stubbing is a potential code smell that points out too much stubbing</li>

- *

- * <li> Once stubbed, the method will always return stubbed value regardless

- * of how many times it is called. </li>

- *

- * <li> Last stubbing is more important - when you stubbed the same method with

- * the same arguments many times.

- * Other words: <b>the order of stubbing matters</b> but it is only meaningful rarely,

- * e.g. when stubbing exactly the same method calls or sometimes when argument matchers are used, etc.</li>

- *

- * </ul>

- *

- *

- *

- * <h3 id="3">3. <a class="meaningful_link" href="#argument_matchers">Argument matchers</a></h3>

- *

- * Mockito verifies argument values in natural java style: by using an <code>equals()</code> method.

- * Sometimes, when extra flexibility is required then you might use argument matchers:

- *

- * <pre class="code"><code class="java">

- * //stubbing using built-in anyInt() argument matcher

- * when(mockedList.get(anyInt())).thenReturn("element");

- *

- * //stubbing using hamcrest (let's say isValid() returns your own hamcrest matcher):

- * when(mockedList.contains(argThat(isValid()))).thenReturn("element");

- *

- * //following prints "element"

- * System.out.println(mockedList.get(999));

- *

- * //<b>you can also verify using an argument matcher</b>

- * verify(mockedList).get(anyInt());

- * </code></pre>

- *

- * <p>

- * Argument matchers allow flexible verification or stubbing.

- * {@link Matchers Click here to see} more built-in matchers

- * and examples of <b>custom argument matchers / hamcrest matchers</b>.

- * <p>

- * For information solely on <b>custom argument matchers</b> check out javadoc for {@link ArgumentMatcher} class.

- * <p>

- * Be reasonable with using complicated argument matching.

- * The natural matching style using <code>equals()</code> with occasional <code>anyX()</code> matchers tend to give clean & simple tests.

- * Sometimes it's just better to refactor the code to allow <code>equals()</code> matching or even implement <code>equals()</code> method to help out with testing.

- * <p>

- * Also, read <a href="#15">section 15</a> or javadoc for {@link ArgumentCaptor} class.

- * {@link ArgumentCaptor} is a special implementation of an argument matcher that captures argument values for further assertions.

- * <p>

- * <b>Warning on argument matchers:</b>

- * <p>

- * If you are using argument matchers, <b>all arguments</b> have to be provided

- * by matchers.

- * <p>

- * E.g: (example shows verification but the same applies to stubbing):

- *

- * <pre class="code"><code class="java">

- *   verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);

- *   //above is correct - eq() is also an argument matcher

- *

- *   verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);

- *   //above is incorrect - exception will be thrown because third argument is given without an argument matcher.

- * </code></pre>

- *

- * <p>

- * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.

- * Internally, they record a matcher on a stack and return a dummy value (usually null).

- * This implementation is due static type safety imposed by java compiler.

- * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.

- *

- *

- *

- *

- * <h3 id="4">4. <a class="meaningful_link" href="#exact_verification">Verifying exact number of invocations</a> /

- * <a class="meaningful_link" href="#at_least_verification">at least x</a> / never</h3>

- *

- * <pre class="code"><code class="java">

- * //using mock

- * mockedList.add("once");

- *

- * mockedList.add("twice");

- * mockedList.add("twice");

- *

- * mockedList.add("three times");

- * mockedList.add("three times");

- * mockedList.add("three times");

- *

- * //following two verifications work exactly the same - times(1) is used by default

- * verify(mockedList).add("once");

- * verify(mockedList, times(1)).add("once");

- *

- * //exact number of invocations verification

- * verify(mockedList, times(2)).add("twice");

- * verify(mockedList, times(3)).add("three times");

- *

- * //verification using never(). never() is an alias to times(0)

- * verify(mockedList, never()).add("never happened");

- *

- * //verification using atLeast()/atMost()

- * verify(mockedList, atLeastOnce()).add("three times");

- * verify(mockedList, atLeast(2)).add("five times");

- * verify(mockedList, atMost(5)).add("three times");

- *

- * </code></pre>

- *

- * <p>

- * <b>times(1) is the default.</b> Therefore using times(1) explicitly can be

- * omitted.

- *

- *

- *

- *

- * <h3 id="5">5. <a class="meaningful_link" href="#stubbing_with_exceptions">Stubbing void methods with exceptions</a></h3>

- *

- * <pre class="code"><code class="java">

- *   doThrow(new RuntimeException()).when(mockedList).clear();

- *

- *   //following throws RuntimeException:

- *   mockedList.clear();

- * </code></pre>

- *

- * Read more about doThrow|doAnswer family of methods in paragraph 12.

- * <p>

- * Initially, {@link Mockito#stubVoid(Object)} was used for stubbing voids.

- * Currently <code>stubVoid()</code> is deprecated in favor of {@link Mockito#doThrow(Throwable)}.

- * This is because of improved readability and consistency with the family of {@link Mockito#doAnswer(Answer)} methods.

- *

- *

- *

- *

- * <h3 id="6">6. <a class="meaningful_link" href="#in_order_verification">Verification in order</a></h3>

- *

- * <pre class="code"><code class="java">

- * // A. Single mock whose methods must be invoked in a particular order

- * List singleMock = mock(List.class);

- *

- * //using a single mock

- * singleMock.add("was added first");

- * singleMock.add("was added second");

- *

- * //create an inOrder verifier for a single mock

- * InOrder inOrder = inOrder(singleMock);

- *

- * //following will make sure that add is first called with "was added first, then with "was added second"

- * inOrder.verify(singleMock).add("was added first");

- * inOrder.verify(singleMock).add("was added second");

- *

- * // B. Multiple mocks that must be used in a particular order

- * List firstMock = mock(List.class);

- * List secondMock = mock(List.class);

- *

- * //using mocks

- * firstMock.add("was called first");

- * secondMock.add("was called second");

- *

- * //create inOrder object passing any mocks that need to be verified in order

- * InOrder inOrder = inOrder(firstMock, secondMock);

- *

- * //following will make sure that firstMock was called before secondMock

- * inOrder.verify(firstMock).add("was called first");

- * inOrder.verify(secondMock).add("was called second");

- *

- * // Oh, and A + B can be mixed together at will

- * </code></pre>

- *

- * Verification in order is flexible - <b>you don't have to verify all

- * interactions</b> one-by-one but only those that you are interested in

- * testing in order.

- * <p>

- * Also, you can create InOrder object passing only mocks that are relevant for

- * in-order verification.

- *

- *

- *

- *

- * <h3 id="7">7. <a class="meaningful_link" href="#never_verification">Making sure interaction(s) never happened on mock</a></h3>

- *

- * <pre class="code"><code class="java">

- * //using mocks - only mockOne is interacted

- * mockOne.add("one");

- *

- * //ordinary verification

- * verify(mockOne).add("one");

- *

- * //verify that method was never called on a mock

- * verify(mockOne, never()).add("two");

- *

- * //verify that other mocks were not interacted

- * verifyZeroInteractions(mockTwo, mockThree);

- *

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="8">8. <a class="meaningful_link" href="#finding_redundant_invocations">Finding redundant invocations</a></h3>

- *

- * <pre class="code"><code class="java">

- * //using mocks

- * mockedList.add("one");

- * mockedList.add("two");

- *

- * verify(mockedList).add("one");

- *

- * //following verification will fail

- * verifyNoMoreInteractions(mockedList);

- * </code></pre>

- *

- * A word of <b>warning</b>:

- * Some users who did a lot of classic, expect-run-verify mocking tend to use <code>verifyNoMoreInteractions()</code> very often, even in every test method.

- * <code>verifyNoMoreInteractions()</code> is not recommended to use in every test method.

- * <code>verifyNoMoreInteractions()</code> is a handy assertion from the interaction testing toolkit. Use it only when it's relevant.

- * Abusing it leads to <strong>overspecified</strong>, <strong>less maintainable</strong> tests. You can find further reading

- * <a href="http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/">here</a>.

- *

- * <p>

- * See also {@link Mockito#never()} - it is more explicit and

- * communicates the intent well.

- * <p>

- *

- *

- *

- *

- * <h3 id="9">9. <a class="meaningful_link" href="#mock_annotation">Shorthand for mocks creation - <code>&#064;Mock</code> annotation</a></h3>

- *

- * <ul>

- * <li>Minimizes repetitive mock creation code.</li>

- * <li>Makes the test class more readable.</li>

- * <li>Makes the verification error easier to read because the <b>field name</b>

- * is used to identify the mock.</li>

- * </ul>

- *

- * <pre class="code"><code class="java">

- *   public class ArticleManagerTest {

- *

- *       &#064;Mock private ArticleCalculator calculator;

- *       &#064;Mock private ArticleDatabase database;

- *       &#064;Mock private UserProvider userProvider;

- *

- *       private ArticleManager manager;

- * </code></pre>

- *

- * <b>Important!</b> This needs to be somewhere in the base class or a test

- * runner:

- *

- * <pre class="code"><code class="java">

- * MockitoAnnotations.initMocks(testClass);

- * </code></pre>

- *

- * You can use built-in runner: {@link MockitoJUnitRunner} or a rule: {@link MockitoRule}.

- * <p>

- * Read more here: {@link MockitoAnnotations}

- *

- *

- *

- *

- * <h3 id="10">10. <a class="meaningful_link" href="#stubbing_consecutive_calls">Stubbing consecutive calls</a> (iterator-style stubbing)</h3>

- *

- * Sometimes we need to stub with different return value/exception for the same

- * method call. Typical use case could be mocking iterators.

- * Original version of Mockito did not have this feature to promote simple mocking.

- * For example, instead of iterators one could use {@link Iterable} or simply

- * collections. Those offer natural ways of stubbing (e.g. using real

- * collections). In rare scenarios stubbing consecutive calls could be useful,

- * though:

- * <p>

- *

- * <pre class="code"><code class="java">

- * when(mock.someMethod("some arg"))

- *   .thenThrow(new RuntimeException())

- *   .thenReturn("foo");

- *

- * //First call: throws runtime exception:

- * mock.someMethod("some arg");

- *

- * //Second call: prints "foo"

- * System.out.println(mock.someMethod("some arg"));

- *

- * //Any consecutive call: prints "foo" as well (last stubbing wins).

- * System.out.println(mock.someMethod("some arg"));

- * </code></pre>

- *

- * Alternative, shorter version of consecutive stubbing:

- *

- * <pre class="code"><code class="java">

- * when(mock.someMethod("some arg"))

- *   .thenReturn("one", "two", "three");

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="11">11. <a class="meaningful_link" href="#answer_stubs">Stubbing with callbacks</a></h3>

- *

- * Allows stubbing with generic {@link Answer} interface.

- * <p>

- * Yet another controversial feature which was not included in Mockito

- * originally. We recommend using simple stubbing with <code>thenReturn()</code> or

- * <code>thenThrow()</code> only. Those two should be <b>just enough</b> to test/test-drive

- * any clean & simple code.

- *

- * <pre class="code"><code class="java">

- * when(mock.someMethod(anyString())).thenAnswer(new Answer() {

- *     Object answer(InvocationOnMock invocation) {

- *         Object[] args = invocation.getArguments();

- *         Object mock = invocation.getMock();

- *         return "called with arguments: " + args;

- *     }

- * });

- *

- * //Following prints "called with arguments: foo"

- * System.out.println(mock.someMethod("foo"));

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="12">12. <a class="meaningful_link" href="#do_family_methods_stubs"><code>doReturn()</code>|<code>doThrow()</code>|

- * <code>doAnswer()</code>|<code>doNothing()</code>|<code>doCallRealMethod()</code> family of methods</a></h3>

- *

- * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not

- * like void methods inside brackets...

- * <p>

- * {@link Mockito#doThrow(Throwable)} replaces the {@link Mockito#stubVoid(Object)} method for stubbing voids.

- * The main reason is improved readability and consistency with the family of <code>doAnswer()</code> methods.

- * <p>

- * Use <code>doThrow()</code> when you want to stub a void method with an exception:

- * <pre class="code"><code class="java">

- *   doThrow(new RuntimeException()).when(mockedList).clear();

- *

- *   //following throws RuntimeException:

- *   mockedList.clear();

- * </code></pre>

- *

- * <p>

- * You can use <code>doThrow()</code>, <code>doAnswer()</code>, <code>doNothing()</code>, <code>doReturn()</code>

- * and <code>doCallRealMethod()</code> in place of the corresponding call with <code>when()</code>, for any method.

- * It is necessary when you

- * <ul>

- *     <li>stub void methods</li>

- *     <li>stub methods on spy objects (see below)</li>

- *     <li>stub the same method more than once, to change the behaviour of a mock in the middle of a test.</li>

- * </ul>

- * but you may prefer to use these methods in place of the alternative with <code>when()</code>, for all of your stubbing calls.

- * <p>

- * Read more about these methods:

- * <p>

- * {@link Mockito#doReturn(Object)}

- * <p>

- * {@link Mockito#doThrow(Throwable)}

- * <p>

- * {@link Mockito#doThrow(Class)}

- * <p>

- * {@link Mockito#doAnswer(Answer)}

- * <p>

- * {@link Mockito#doNothing()}

- * <p>

- * {@link Mockito#doCallRealMethod()}

- *

- *

- *

- *

- * <h3 id="13">13. <a class="meaningful_link" href="#spy">Spying on real objects</a></h3>

- *

- * You can create spies of real objects. When you use the spy then the <b>real</b> methods are called

- * (unless a method was stubbed).

- * <p>

- * Real spies should be used <b>carefully and occasionally</b>, for example when dealing with legacy code.

- *

- * <p>

- * Spying on real objects can be associated with "partial mocking" concept.

- * <b>Before the release 1.8</b>, Mockito spies were not real partial mocks.

- * The reason was we thought partial mock is a code smell.

- * At some point we found legitimate use cases for partial mocks

- * (3rd party interfaces, interim refactoring of legacy code, the full article is <a href=

- * "http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring"

- * >here</a>)

- * <p>

- *

- * <pre class="code"><code class="java">

- *   List list = new LinkedList();

- *   List spy = spy(list);

- *

- *   //optionally, you can stub out some methods:

- *   when(spy.size()).thenReturn(100);

- *

- *   //using the spy calls <b>*real*</b> methods

- *   spy.add("one");

- *   spy.add("two");

- *

- *   //prints "one" - the first element of a list

- *   System.out.println(spy.get(0));

- *

- *   //size() method was stubbed - 100 is printed

- *   System.out.println(spy.size());

- *

- *   //optionally, you can verify

- *   verify(spy).add("one");

- *   verify(spy).add("two");

- * </code></pre>

- *

- * <h4>Important gotcha on spying real objects!</h4>

- * <ol>

- * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.

- * Therefore when using spies please consider <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code> family of

- * methods for stubbing. Example:

- *

- * <pre class="code"><code class="java">

- *   List list = new LinkedList();

- *   List spy = spy(list);

- *

- *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)

- *   when(spy.get(0)).thenReturn("foo");

- *

- *   //You have to use doReturn() for stubbing

- *   doReturn("foo").when(spy).get(0);

- * </code></pre>

- * </li>

- *

- * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.

- * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction

- * and their effect on real instance state.

- * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,

- * you won't see any effects on the real instance.

- * </li>

- *

- * <li>Watch out for final methods.

- * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.

- * Also you won't be able to verify those method as well.

- * </li>

- * </ol>

- *

- *

- *

- *

- * <h3 id="14">14. Changing <a class="meaningful_link" href="#defaultreturn">default return values of unstubbed invocations</a> (Since 1.7)</h3>

- *

- * You can create a mock with specified strategy for its return values.

- * It's quite advanced feature and typically you don't need it to write decent tests.

- * However, it can be helpful for working with <b>legacy systems</b>.

- * <p>

- * It is the default answer so it will be used <b>only when you don't</b> stub the method call.

- *

- * <pre class="code"><code class="java">

- *   Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);

- *   Foo mockTwo = mock(Foo.class, new YourOwnAnswer());

- * </code></pre>

- *

- * <p>

- * Read more about this interesting implementation of <i>Answer</i>: {@link Mockito#RETURNS_SMART_NULLS}

- *

- *

- *

- *

- * <h3 id="15">15. <a class="meaningful_link" href="#captors">Capturing arguments</a> for further assertions (Since 1.8.0)</h3>

- *

- * Mockito verifies argument values in natural java style: by using an <code>equals()</code> method.

- * This is also the recommended way of matching arguments because it makes tests clean & simple.

- * In some situations though, it is helpful to assert on certain arguments after the actual verification.

- * For example:

- * <pre class="code"><code class="java">

- *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);

- *   verify(mock).doSomething(argument.capture());

- *   assertEquals("John", argument.getValue().getName());

- * </code></pre>

- *

- * <b>Warning:</b> it is recommended to use ArgumentCaptor with verification <b>but not</b> with stubbing.

- * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.

- * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.

- * <p>

- * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).

- * Both techniques can be used for making sure certain arguments where passed to mocks.

- * However, ArgumentCaptor may be a better fit if:

- * <ul>

- * <li>custom argument matcher is not likely to be reused</li>

- * <li>you just need it to assert on argument values to complete verification</li>

- * </ul>

- * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.

- *

- *

- *

- *

- * <h3 id="16">16. <a class="meaningful_link" href="#partial_mocks">Real partial mocks</a> (Since 1.8.0)</h3>

- *

- *  Finally, after many internal debates & discussions on the mailing list, partial mock support was added to Mockito.

- *  Previously we considered partial mocks as code smells. However, we found a legitimate use case for partial mocks - more reading:

- *  <a href="http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring">here</a>

- *  <p>

- *  <b>Before release 1.8</b> <code>spy()</code> was not producing real partial mocks and it was confusing for some users.

- *  Read more about spying: <a href="#13">here</a> or in javadoc for {@link Mockito#spy(Object)} method.

- *  <p>

- *  <pre class="code"><code class="java">

- *    //you can create partial mock with spy() method:

- *    List list = spy(new LinkedList());

- *

- *    //you can enable partial mock capabilities selectively on mocks:

- *    Foo mock = mock(Foo.class);

- *    //Be sure the real implementation is 'safe'.

- *    //If real implementation throws exceptions or depends on specific state of the object then you're in trouble.

- *    when(mock.someMethod()).thenCallRealMethod();

- *  </code></pre>

- *

- * As usual you are going to read <b>the partial mock warning</b>:

- * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.

- * How does partial mock fit into this paradigm? Well, it just doesn't...

- * Partial mock usually means that the complexity has been moved to a different method on the same object.

- * In most cases, this is not the way you want to design your application.

- * <p>

- * However, there are rare cases when partial mocks come handy:

- * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)

- * However, I wouldn't use partial mocks for new, test-driven & well-designed code.

- *

- *

- *

- *

- * <h3 id="17">17. <a class="meaningful_link" href="#resetting_mocks">Resetting mocks</a> (Since 1.8.0)</h3>

- *

- * Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.

- * Normally, you don't need to reset your mocks, just create new mocks for each test method.

- * <p>

- * Instead of <code>reset()</code> please consider writing simple, small and focused test methods over lengthy, over-specified tests.

- * <b>First potential code smell is <code>reset()</code> in the middle of the test method.</b> This probably means you're testing too much.

- * Follow the whisper of your test methods: "Please keep us small & focused on single behavior".

- * There are several threads about it on mockito mailing list.

- * <p>

- * The only reason we added <code>reset()</code> method is to

- * make it possible to work with container-injected mocks.

- * See issue 55 (<a href="http://code.google.com/p/mockito/issues/detail?id=55">here</a>)

- * or FAQ (<a href="http://code.google.com/p/mockito/wiki/FAQ">here</a>).

- * <p>

- * <b>Don't harm yourself.</b> <code>reset()</code> in the middle of the test method is a code smell (you're probably testing too much).

- * <pre class="code"><code class="java">

- *   List mock = mock(List.class);

- *   when(mock.size()).thenReturn(10);

- *   mock.add(1);

- *

- *   reset(mock);

- *   //at this point the mock forgot any interactions & stubbing

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="18">18. <a class="meaningful_link" href="#framework_validation">Troubleshooting & validating framework usage</a> (Since 1.8.0)</h3>

- *

- * First of all, in case of any trouble, I encourage you to read the Mockito FAQ:

- * <a href="http://code.google.com/p/mockito/wiki/FAQ">http://code.google.com/p/mockito/wiki/FAQ</a>

- * <p>

- * In case of questions you may also post to mockito mailing list:

- * <a href="http://groups.google.com/group/mockito">http://groups.google.com/group/mockito</a>

- * <p>

- * Next, you should know that Mockito validates if you use it correctly <b>all the time</b>.

- * However, there's a gotcha so please read the javadoc for {@link Mockito#validateMockitoUsage()}

- *

- *

- *

- *

- * <h3 id="19">19. <a class="meaningful_link" href="#bdd_mockito">Aliases for behavior driven development</a> (Since 1.8.0)</h3>

- *

- * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.

- * This is exactly how we write our tests and we warmly encourage you to do so!

- * <p>

- * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>

- * <p>

- * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.

- * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.

- * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.

- * Now it really nicely integrates with the <b>given</b> component of a BDD style test!

- * <p>

- * Here is how the test might look like:

- * <pre class="code"><code class="java">

- * import static org.mockito.BDDMockito.*;

- *

- * Seller seller = mock(Seller.class);

- * Shop shop = new Shop(seller);

- *

- * public void shouldBuyBread() throws Exception {

- *   //given

- *   given(seller.askForBread()).willReturn(new Bread());

- *

- *   //when

- *   Goods goods = shop.buyBread();

- *

- *   //then

- *   assertThat(goods, containBread());

- * }

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="20">20. <a class="meaningful_link" href="#serializable_mocks">Serializable mocks</a> (Since 1.8.1)</h3>

- *

- * Mocks can be made serializable. With this feature you can use a mock in a place that requires dependencies to be serializable.

- * <p>

- * WARNING: This should be rarely used in unit testing.

- * <p>

- * The behaviour was implemented for a specific use case of a BDD spec that had an unreliable external dependency.  This

- * was in a web environment and the objects from the external dependency were being serialized to pass between layers.

- * <p>

- * To create serializable mock use {@link MockSettings#serializable()}:

- * <pre class="code"><code class="java">

- *   List serializableMock = mock(List.class, withSettings().serializable());

- * </code></pre>

- * <p>

- * The mock can be serialized assuming all the normal <a href='http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html'>

- * serialization requirements</a> are met by the class.

- * <p>

- * Making a real object spy serializable is a bit more effort as the spy(...) method does not have an overloaded version

- * which accepts MockSettings. No worries, you will hardly ever use it.

- *

- * <pre class="code"><code class="java">

- * List&lt;Object&gt; list = new ArrayList&lt;Object&gt;();

- * List&lt;Object&gt; spy = mock(ArrayList.class, withSettings()

- *                 .spiedInstance(list)

- *                 .defaultAnswer(CALLS_REAL_METHODS)

- *                 .serializable());

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="21">21. New annotations: <a class="meaningful_link" href="#captor_annotation"><code>&#064;Captor</code></a>,

- * <a class="meaningful_link" href="#spy_annotation"><code>&#064;Spy</code></a>,

- * <a class="meaningful_link" href="#injectmocks_annotation"><code>&#064;InjectMocks</code></a> (Since 1.8.3)</h3>

- *

- * <p>

- * Release 1.8.3 brings new annotations that may be helpful on occasion:

- *

- * <ul>

- * <li>&#064;{@link Captor} simplifies creation of {@link ArgumentCaptor}

- * - useful when the argument to capture is a nasty generic class and you want to avoid compiler warnings

- * <li>&#064;{@link Spy} - you can use it instead {@link Mockito#spy(Object)}.

- * <li>&#064;{@link InjectMocks} - injects mock or spy fields into tested object automatically.

- * </ul>

- *

- * <p>

- * Note that &#064;{@link InjectMocks} can also be used in combination with the &#064;{@link Spy} annotation, it means

- * that Mockito will inject mocks into the partial mock under test. This complexity is another good reason why you

- * should only use partial mocks as a last resort. See point 16 about partial mocks.

- *

- * <p>

- * All new annotations are <b>*only*</b> processed on {@link MockitoAnnotations#initMocks(Object)}.

- * Just like for &#064;{@link Mock} annotation you can use the built-in runner: {@link MockitoJUnitRunner} or rule:

- * {@link MockitoRule}.

- * <p>

- *

- *

- *

- *

- * <h3 id="22">22. <a class="meaningful_link" href="#verification_timeout">Verification with timeout</a> (Since 1.8.5)</h3>

- * <p>

- * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired

- * interaction rather than fails immediately if had not already happened. May be useful for testing in concurrent

- * conditions.

- * <p>

- * It feels this feature should be used rarely - figure out a better way of testing your multi-threaded system.

- * <p>

- * Not yet implemented to work with InOrder verification.

- * <p>

- * Examples:

- * <p>

- * <pre class="code"><code class="java">

- *   //passes when someMethod() is called within given time span

- *   verify(mock, timeout(100)).someMethod();

- *   //above is an alias to:

- *   verify(mock, timeout(100).times(1)).someMethod();

- *

- *   //passes when someMethod() is called <b>*exactly*</b> 2 times within given time span

- *   verify(mock, timeout(100).times(2)).someMethod();

- *

- *   //passes when someMethod() is called <b>*at least*</b> 2 times within given time span

- *   verify(mock, timeout(100).atLeast(2)).someMethod();

- *

- *   //verifies someMethod() within given time span using given verification mode

- *   //useful only if you have your own custom verification modes.

- *   verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="23">23. <a class="meaningful_link" href="#automatic_instantiation">Automatic instantiation of <code>&#064;Spies</code>,

- * <code>&#064;InjectMocks</code></a> and <a class="meaningful_link" href="#constructor_injection">constructor injection goodness</a> (Since 1.9.0)</h3>

- *

- * <p>

- * Mockito will now try to instantiate &#064;{@link Spy} and will instantiate &#064;{@link InjectMocks} fields

- * using <b>constructor</b> injection, <b>setter</b> injection, or <b>field</b> injection.

- * <p>

- * To take advantage of this feature you need to use {@link MockitoAnnotations#initMocks(Object)}, {@link MockitoJUnitRunner}

- * or {@link MockitoRule}.

- * <p>

- * Read more about available tricks and the rules of injection in the javadoc for {@link InjectMocks}

- * <pre class="code"><code class="java">

- * //instead:

- * &#064;Spy BeerDrinker drinker = new BeerDrinker();

- * //you can write:

- * &#064;Spy BeerDrinker drinker;

- *

- * //same applies to &#064;InjectMocks annotation:

- * &#064;InjectMocks LocalPub;

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="24">24. <a class="meaningful_link" href="#one_liner_stub">One-liner stubs</a> (Since 1.9.0)</h3>

- * <p>

- * Mockito will now allow you to create mocks when stubbing.

- * Basically, it allows to create a stub in one line of code.

- * This can be helpful to keep test code clean.

- * For example, some boring stub can be created & stubbed at field initialization in a test:

- * <pre class="code"><code class="java">

- * public class CarTest {

- *   Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();

- *

- *   &#064;Test public void should... {}

- * </code></pre>

- *

- *

- *

- *

- * <h3 id="25">25. <a class="meaningful_link" href="#ignore_stubs_verification">Verification ignoring stubs</a> (Since 1.9.0)</h3>

- * <p>

- * Mockito will now allow to ignore stubbing for the sake of verification.

- * Sometimes useful when coupled with <code>verifyNoMoreInteractions()</code> or verification <code>inOrder()</code>.

- * Helps avoiding redundant verification of stubbed calls - typically we're not interested in verifying stubs.

- * <p>

- * <b>Warning</b>, <code>ignoreStubs()</code> might lead to overuse of verifyNoMoreInteractions(ignoreStubs(...));

- * Bear in mind that Mockito does not recommend bombarding every test with <code>verifyNoMoreInteractions()</code>

- * for the reasons outlined in javadoc for {@link Mockito#verifyNoMoreInteractions(Object...)}

- * <p>Some examples:

- * <pre class="code"><code class="java">

- * verify(mock).foo();

- * verify(mockTwo).bar();

- *

- * //ignores all stubbed methods:

- * verifyNoMoreInvocations(ignoreStubs(mock, mockTwo));

- *

- * //creates InOrder that will ignore stubbed

- * InOrder inOrder = inOrder(ignoreStubs(mock, mockTwo));

- * inOrder.verify(mock).foo();

- * inOrder.verify(mockTwo).bar();

- * inOrder.verifyNoMoreInteractions();

- * </code></pre>

- * <p>

- * Advanced examples and more details can be found in javadoc for {@link Mockito#ignoreStubs(Object...)}

- *

- *

- *

- *

- * <h3 id="26">26. <a class="meaningful_link" href="#mocking_details">Mocking details</a> (Since 1.9.5)</h3>

- * <p>

- * To identify whether a particular object is a mock or a spy:

- * <pre class="code"><code class="java">

- *     Mockito.mockingDetails(someObject).isMock();

- *     Mockito.mockingDetails(someObject).isSpy();

- * </code></pre>

- * Both the {@link MockingDetails#isMock} and {@link MockingDetails#isSpy()} methods return <code>boolean</code>.

- * As a spy is just a different kind of mock, <code>isMock()</code> returns true if the object is a spy.

- * In future Mockito versions MockingDetails may grow and provide other useful information about the mock,

- * e.g. invocations, stubbing info, etc.

- *

- *

- *

- *

- * <h3 id="27">27. <a class="meaningful_link" href="#delegating_call_to_real_instance">Delegate calls to real instance</a> (Since 1.9.5)</h3>

- *

- * <p>Useful for spies or partial mocks of objects <strong>that are difficult to mock or spy</strong> using the usual spy API.

- * Since Mockito 1.10.11, the delegate may or may not be of the same type as the mock.

- * If the type is different, a matching method needs to be found on delegate type otherwise an exception is thrown.

- *

- * Possible use cases for this feature:

- * <ul>

- *     <li>Final classes but with an interface</li>

- *     <li>Already custom proxied object</li>

- *     <li>Special objects with a finalize method, i.e. to avoid executing it 2 times</li>

- * </ul>

- *

- * <p>The difference with the regular spy:

- * <ul>

- *   <li>

- *     The regular spy ({@link #spy(Object)}) contains <strong>all</strong> state from the spied instance

- *     and the methods are invoked on the spy. The spied instance is only used at mock creation to copy the state from.

- *     If you call a method on a regular spy and it internally calls other methods on this spy, those calls are remembered

- *     for verifications, and they can be effectively stubbed.

- *   </li>

- *   <li>

- *     The mock that delegates simply delegates all methods to the delegate.

- *     The delegate is used all the time as methods are delegated onto it.

- *     If you call a method on a mock that delegates and it internally calls other methods on this mock,

- *     those calls are <strong>not</strong> remembered for verifications, stubbing does not have effect on them, too.

- *     Mock that delegates is less powerful than the regular spy but it is useful when the regular spy cannot be created.

- *   </li>

- * </ul>

- *

- * <p>

- * See more information in docs for {@link AdditionalAnswers#delegatesTo(Object)}.

- *

- *

- *

- *

- * <h3 id="28">28. <a class="meaningful_link" href="#mock_maker_plugin"><code>MockMaker</code> API</a> (Since 1.9.5)</h3>

- * <p>Driven by requirements and patches from Google Android guys Mockito now offers an extension point

- *   that allows replacing the proxy generation engine. By default, Mockito uses cglib to create dynamic proxies.

- * <p>The extension point is for advanced users that want to extend Mockito. For example, it is now possible

- *   to use Mockito for Android testing with a help of dexmaker.

- * <p>For more details, motivations and examples please refer to

- * the docs for {@link org.mockito.plugins.MockMaker}.

- *

- *

- *

- *

- * <h3 id="29">29. <a class="meaningful_link" href="#BDD_behavior_verification">(new) BDD style verification</a> (Since 1.10.0)</h3>

- *

- * Enables Behavior Driven Development (BDD) style verification by starting verification with the BDD <b>then</b> keyword.

- *

- * <pre class="code"><code class="java">

- *   then(person).should(times(2)).ride(bike);

- * </code></pre>

- *

- * For more information and an example see {@link BDDMockito#then(Object)}}

- *

- * <h3 id="30">30. <a class="meaningful_link" href="#spying_abstract_classes">(new) Spying or mocking abstract classes (Since 1.10.12)</a></h3>

- *

- * It is now possible to conveniently spy on abstract classes. Note that overusing spies hints at code design smells (see {@link #spy(Object)}).

- * <p>

- * Previously, spying was only possible on instances of objects.

- * New API makes it possible to use constructor when creating an instance of the mock.

- * This is particularly useful for mocking abstract classes because the user is no longer required to provide an instance of the abstract class.

- * At the moment, only parameter-less constructor is supported, let us know if it is not enough.

- *

- * <pre class="code"><code class="java">

- *   //convenience API, new overloaded spy() method:

- *   SomeAbstract spy = spy(SomeAbstract.class);

- *

- *   //Robust API, via settings builder:

- *   OtherAbstract spy = mock(OtherAbstract.class, withSettings()

- *      .useConstructor().defaultAnswer(CALLS_REAL_METHODS));

- *

- *   //Mocking a non-static inner abstract class:

- *   InnerAbstract spy = mock(InnerAbstract.class, withSettings()

- *      .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));

- * </code></pre>

- *

- * For more information please see {@link MockSettings#useConstructor()}.

- */

-@SuppressWarnings("unchecked")

-public class Mockito extends Matchers {

-

-    static final MockitoCore MOCKITO_CORE = new MockitoCore();

-

-    /**

-     * The default <code>Answer</code> of every mock <b>if</b> the mock was not stubbed.

-     * Typically it just returns some empty value.

-     * <p>

-     * {@link Answer} can be used to define the return values of unstubbed invocations.

-     * <p>

-     * This implementation first tries the global configuration.

-     * If there is no global configuration then it uses {@link ReturnsEmptyValues} (returns zeros, empty collections, nulls, etc.)

-     */

-    public static final Answer<Object> RETURNS_DEFAULTS = Answers.RETURNS_DEFAULTS.get();

-

-    /**

-     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.

-     * <p>

-     * {@link Answer} can be used to define the return values of unstubbed invocations.

-     * <p>

-     * This implementation can be helpful when working with legacy code.

-     * Unstubbed methods often return null. If your code uses the object returned by an unstubbed call you get a NullPointerException.

-     * This implementation of Answer <b>returns SmartNull instead of null</b>.

-     * <code>SmartNull</code> gives nicer exception message than NPE because it points out the line where unstubbed method was called. You just click on the stack trace.

-     * <p>

-     * <code>ReturnsSmartNulls</code> first tries to return ordinary return values (see {@link ReturnsMoreEmptyValues})

-     * then it tries to return SmartNull. If the return type is final then plain null is returned.

-     * <p>

-     * <code>ReturnsSmartNulls</code> will be probably the default return values strategy in Mockito 2.0.

-     * <p>

-     * Example:

-     * <pre class="code"><code class="java">

-     *   Foo mock = (Foo.class, RETURNS_SMART_NULLS);

-     *

-     *   //calling unstubbed method here:

-     *   Stuff stuff = mock.getStuff();

-     *

-     *   //using object returned by unstubbed call:

-     *   stuff.doSomething();

-     *

-     *   //Above doesn't yield NullPointerException this time!

-     *   //Instead, SmartNullPointerException is thrown.

-     *   //Exception's cause links to unstubbed <i>mock.getStuff()</i> - just click on the stack trace.

-     * </code></pre>

-     */

-    public static final Answer<Object> RETURNS_SMART_NULLS = Answers.RETURNS_SMART_NULLS.get();

-

-    /**

-     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}

-     * <p>

-     * {@link Answer} can be used to define the return values of unstubbed invocations.

-     * <p>

-     * This implementation can be helpful when working with legacy code.

-     * <p>

-     * ReturnsMocks first tries to return ordinary return values (see {@link ReturnsMoreEmptyValues})

-     * then it tries to return mocks. If the return type cannot be mocked (e.g. is final) then plain null is returned.

-     * <p>

-     */

-    public static final Answer<Object> RETURNS_MOCKS = Answers.RETURNS_MOCKS.get();

-

-    /**

-     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.

-     * <p>

-     * Example that shows how deep stub works:

-     * <pre class="code"><code class="java">

-     *   Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);

-     *

-     *   // note that we're stubbing a chain of methods here: getBar().getName()

-     *   when(mock.getBar().getName()).thenReturn("deep");

-     *

-     *   // note that we're chaining method calls: getBar().getName()

-     *   assertEquals("deep", mock.getBar().getName());

-     * </code></pre>

-     * </p>

-     *

-     * <p>

-     * <strong>WARNING: </strong>

-     * This feature should rarely be required for regular clean code! Leave it for legacy code.

-     * Mocking a mock to return a mock, to return a mock, (...), to return something meaningful

-     * hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).

-     * </p>

-     *

-     * <p>

-     * Good quote I've seen one day on the web: <strong>every time a mock returns a mock a fairy dies</strong>.

-     * </p>

-     *

-     * <p>

-     * Please note that this answer will return existing mocks that matches the stub. This

-     * behavior is ok with deep stubs and allows verification to work on the last mock of the chain.

-     * <pre class="code"><code class="java">

-     *   when(mock.getBar(anyString()).getThingy().getName()).thenReturn("deep");

-     *

-     *   mock.getBar("candy bar").getThingy().getName();

-     *

-     *   assertSame(mock.getBar(anyString()).getThingy().getName(), mock.getBar(anyString()).getThingy().getName());

-     *   verify(mock.getBar("candy bar").getThingy()).getName();

-     *   verify(mock.getBar(anyString()).getThingy()).getName();

-     * </code></pre>

-     * </p>

-     *

-     * <p>

-     * Verification only works with the last mock in the chain. You can use verification modes.

-     * <pre class="code"><code class="java">

-     *   when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");

-     *   when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep");

-     *   when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep");

-     *

-     *   person.getAddress("the docks").getStreet().getName();

-     *   person.getAddress("the docks").getStreet().getLongName();

-     *   person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();

-     *   person.getAddress("the docks").getStreet(Locale.CHINESE).getName();

-     *

-     *   // note that we are actually referring to the very last mock in the stubbing chain.

-     *   InOrder inOrder = inOrder(

-     *       person.getAddress("the docks").getStreet(),

-     *       person.getAddress("the docks").getStreet(Locale.CHINESE),

-     *       person.getAddress("the docks").getStreet(Locale.ITALIAN)

-     *   );

-     *   inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();

-     *   inOrder.verify(person.getAddress("the docks").getStreet()).getLongName();

-     *   inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1)).getName();

-     *   inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();

-     * </code></pre>

-     * </p>

-     *

-     * <p>

-     * How deep stub work internally?

-     * <pre class="code"><code class="java">

-     *   //this:

-     *   Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);

-     *   when(mock.getBar().getName(), "deep");

-     *

-     *   //is equivalent of

-     *   Foo foo = mock(Foo.class);

-     *   Bar bar = mock(Bar.class);

-     *   when(foo.getBar()).thenReturn(bar);

-     *   when(bar.getName()).thenReturn("deep");

-     * </code></pre>

-     * </p>

-     *

-     * <p>

-     * This feature will not work when any return type of methods included in the chain cannot be mocked

-     * (for example: is a primitive or a final class). This is because of java type system.

-     * </p>

-     */

-    public static final Answer<Object> RETURNS_DEEP_STUBS = Answers.RETURNS_DEEP_STUBS.get();

-

-    /**

-     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}

-     * <p>

-     * {@link Answer} can be used to define the return values of unstubbed invocations.

-     * <p>

-     * This implementation can be helpful when working with legacy code.

-     * When this implementation is used, unstubbed methods will delegate to the real implementation.

-     * This is a way to create a partial mock object that calls real methods by default.

-     * <p>

-     * As usual you are going to read <b>the partial mock warning</b>:

-     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.

-     * How does partial mock fit into this paradigm? Well, it just doesn't...

-     * Partial mock usually means that the complexity has been moved to a different method on the same object.

-     * In most cases, this is not the way you want to design your application.

-     * <p>

-     * However, there are rare cases when partial mocks come handy:

-     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)

-     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.

-     * <p>

-     * Example:

-     * <pre class="code"><code class="java">

-     * Foo mock = mock(Foo.class, CALLS_REAL_METHODS);

-     *

-     * // this calls the real implementation of Foo.getSomething()

-     * value = mock.getSomething();

-     *

-     * when(mock.getSomething()).thenReturn(fakeValue);

-     *

-     * // now fakeValue is returned

-     * value = mock.getSomething();

-     * </code></pre>

-     */

-    public static final Answer<Object> CALLS_REAL_METHODS = Answers.CALLS_REAL_METHODS.get();

-

-    /**

-     * Creates mock object of given class or interface.

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param classToMock class or interface to mock

-     * @return mock object

-     */

-    public static <T> T mock(Class<T> classToMock) {

-        return mock(classToMock, withSettings().defaultAnswer(RETURNS_DEFAULTS));

-    }

-

-    /**

-     * Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.

-     * <p>

-     * Beware that naming mocks is not a solution for complex code which uses too many mocks or collaborators.

-     * <b>If you have too many mocks then refactor the code</b> so that it's easy to test/debug without necessity of naming mocks.

-     * <p>

-     * <b>If you use <code>&#064;Mock</code> annotation then you've got naming mocks for free!</b> <code>&#064;Mock</code> uses field name as mock name. {@link Mock Read more.}

-     * <p>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param classToMock class or interface to mock

-     * @param name of the mock

-     * @return mock object

-     */

-    public static <T> T mock(Class<T> classToMock, String name) {

-        return mock(classToMock, withSettings()

-                .name(name)

-                .defaultAnswer(RETURNS_DEFAULTS));

-    }

-

-    /**

-     * Returns a MockingDetails instance that enables inspecting a particular object for Mockito related information.

-     * Can be used to find out if given object is a Mockito mock

-     * or to find out if a given mock is a spy or mock.

-     * <p>

-     * In future Mockito versions MockingDetails may grow and provide other useful information about the mock,

-     * e.g. invocations, stubbing info, etc.

-     *

-     * @param toInspect - object to inspect. null input is allowed.

-     * @return A {@link org.mockito.MockingDetails} instance.

-     * @since 1.9.5

-     */

-    public static MockingDetails mockingDetails(Object toInspect) {

-        return MOCKITO_CORE.mockingDetails(toInspect);

-    }

-

-    /**

-     * <b>Deprecated : Please use mock(Foo.class, defaultAnswer);</b>

-     * <p>

-     * See {@link Mockito#mock(Class, Answer)}

-     * <p>

-     * Why it is deprecated? ReturnValues is being replaced by Answer

-     * for better consistency & interoperability of the framework.

-     * Answer interface has been in Mockito for a while and it has the same responsibility as ReturnValues.

-     * There's no point in mainting exactly the same interfaces.

-     * <p>

-     * Creates mock with a specified strategy for its return values.

-     * It's quite advanced feature and typically you don't need it to write decent tests.

-     * However it can be helpful when working with legacy systems.

-     * <p>

-     * Obviously return values are used only when you don't stub the method call.

-     *

-     * <pre class="code"><code class="java">

-     *   Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);

-     *   Foo mockTwo = mock(Foo.class, new YourOwnReturnValues());

-     * </code></pre>

-     *

-     * <p>See examples in javadoc for {@link Mockito} class</p>

-     *

-     * @param classToMock class or interface to mock

-     * @param returnValues default return values for unstubbed methods

-     *

-     * @return mock object

-     *

-     * @deprecated <b>Please use mock(Foo.class, defaultAnswer);</b>

-     */

-    @Deprecated

-    public static <T> T mock(Class<T> classToMock, ReturnValues returnValues) {

-        return mock(classToMock, withSettings().defaultAnswer(new AnswerReturnValuesAdapter(returnValues)));

-    }

-

-    /**

-     * Creates mock with a specified strategy for its answers to interactions.

-     * It's quite advanced feature and typically you don't need it to write decent tests.

-     * However it can be helpful when working with legacy systems.

-     * <p>

-     * It is the default answer so it will be used <b>only when you don't</b> stub the method call.

-     *

-     * <pre class="code"><code class="java">

-     *   Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);

-     *   Foo mockTwo = mock(Foo.class, new YourOwnAnswer());

-     * </code></pre>

-     *

-     * <p>See examples in javadoc for {@link Mockito} class</p>

-     *

-     * @param classToMock class or interface to mock

-     * @param defaultAnswer default answer for unstubbed methods

-     *

-     * @return mock object

-     */

-    public static <T> T mock(Class<T> classToMock, Answer defaultAnswer) {

-        return mock(classToMock, withSettings().defaultAnswer(defaultAnswer));

-    }

-

-    /**

-     * Creates a mock with some non-standard settings.

-     * <p>

-     * The number of configuration points for a mock grows

-     * so we need a fluent way to introduce new configuration without adding more and more overloaded Mockito.mock() methods.

-     * Hence {@link MockSettings}.

-     * <pre class="code"><code class="java">

-     *   Listener mock = mock(Listener.class, withSettings()

-     *     .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));

-     *   );

-     * </code></pre>

-     * <b>Use it carefully and occasionally</b>. What might be reason your test needs non-standard mocks?

-     * Is the code under test so complicated that it requires non-standard mocks?

-     * Wouldn't you prefer to refactor the code under test so it is testable in a simple way?

-     * <p>

-     * See also {@link Mockito#withSettings()}

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param classToMock class or interface to mock

-     * @param mockSettings additional mock settings

-     * @return mock object

-     */

-    public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {

-        return MOCKITO_CORE.mock(classToMock, mockSettings);

-    }

-

-    /**

-     * Creates a spy of the real object. The spy calls <b>real</b> methods unless they are stubbed.

-     * <p>

-     * Real spies should be used <b>carefully and occasionally</b>, for example when dealing with legacy code.

-     * <p>

-     * As usual you are going to read <b>the partial mock warning</b>:

-     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.

-     * How does partial mock fit into this paradigm? Well, it just doesn't...

-     * Partial mock usually means that the complexity has been moved to a different method on the same object.

-     * In most cases, this is not the way you want to design your application.

-     * <p>

-     * However, there are rare cases when partial mocks come handy:

-     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)

-     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.

-     * <p>

-     * Example:

-     *

-     * <pre class="code"><code class="java">

-     *   List list = new LinkedList();

-     *   List spy = spy(list);

-     *

-     *   //optionally, you can stub out some methods:

-     *   when(spy.size()).thenReturn(100);

-     *

-     *   //using the spy calls <b>real</b> methods

-     *   spy.add("one");

-     *   spy.add("two");

-     *

-     *   //prints "one" - the first element of a list

-     *   System.out.println(spy.get(0));

-     *

-     *   //size() method was stubbed - 100 is printed

-     *   System.out.println(spy.size());

-     *

-     *   //optionally, you can verify

-     *   verify(spy).add("one");

-     *   verify(spy).add("two");

-     * </code></pre>

-     *

-     * <h4>Important gotcha on spying real objects!</h4>

-     * <ol>

-     * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.

-     * Therefore for spies it is recommended to always use <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code>|<code>CallRealMethod</code>

-     * family of methods for stubbing. Example:

-     *

-     * <pre class="code"><code class="java">

-     *   List list = new LinkedList();

-     *   List spy = spy(list);

-     *

-     *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)

-     *   when(spy.get(0)).thenReturn("foo");

-     *

-     *   //You have to use doReturn() for stubbing

-     *   doReturn("foo").when(spy).get(0);

-     * </code></pre>

-     * </li>

-     *

-     * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.

-     * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction

-     * and their effect on real instance state.

-     * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,

-     * you won't see any effects on the real instance.</li>

-     *

-     * <li>Watch out for final methods.

-     * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.

-     * Also you won't be able to verify those method as well.

-     * </li>

-     * </ol>

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * <p>Note that the spy won't have any annotations of the spied type, because CGLIB won't rewrite them.

-     * It may troublesome for code that rely on the spy to have these annotations.</p>

-     *

-     *

-     * @param object

-     *            to spy on

-     * @return a spy of the real object

-     */

-    public static <T> T spy(T object) {

-        return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()

-                .spiedInstance(object)

-                .defaultAnswer(CALLS_REAL_METHODS));

-    }

-

-    /**

-     * Please refer to the documentation of {@link #spy(Object)}.

-     * Overusing spies hints at code design smells.

-     * <p>

-     * This method, in contrast to the original {@link #spy(Object)}, creates a spy based on class instead of an object.

-     * Sometimes it is more convenient to create spy based on the class and avoid providing an instance of a spied object.

-     * This is particularly useful for spying on abstract classes because they cannot be instantiated.

-     * See also {@link MockSettings#useConstructor()}.

-     * <p>

-     * Examples:

-     * <pre class="code"><code class="java">

-     *   SomeAbstract spy = spy(SomeAbstract.class);

-     *

-     *   //Robust API, via settings builder:

-     *   OtherAbstract spy = mock(OtherAbstract.class, withSettings()

-     *      .useConstructor().defaultAnswer(CALLS_REAL_METHODS));

-     *

-     *   //Mocking a non-static inner abstract class:

-     *   InnerAbstract spy = mock(InnerAbstract.class, withSettings()

-     *      .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));

-     * </code></pre>

-     *

-     * @param classToSpy the class to spy

-     * @param <T> type of the spy

-     * @return a spy of the provided class

-     * @since 1.10.12

-     */

-    @Incubating

-    public static <T> T spy(Class<T> classToSpy) {

-        return MOCKITO_CORE.mock(classToSpy, withSettings()

-                .useConstructor()

-                .defaultAnswer(CALLS_REAL_METHODS));

-    }

-

-    /**

-     * Stubs a method call with return value or an exception. E.g:

-     *

-     * <pre class="code"><code class="java">

-     * stub(mock.someMethod()).toReturn(10);

-     *

-     * //you can use flexible argument matchers, e.g:

-     * stub(mock.someMethod(<b>anyString()</b>)).toReturn(10);

-     *

-     * //setting exception to be thrown:

-     * stub(mock.someMethod("some arg")).toThrow(new RuntimeException());

-     *

-     * //you can stub with different behavior for consecutive method calls.

-     * //Last stubbing (e.g: toReturn("foo")) determines the behavior for further consecutive calls.

-     * stub(mock.someMethod("some arg"))

-     *  .toThrow(new RuntimeException())

-     *  .toReturn("foo");

-     * </code></pre>

-     * <p>

-     * Some users find stub() confusing therefore {@link Mockito#when(Object)} is recommended over stub()

-     * <pre class="code"><code class="java">

-     *   //Instead of:

-     *   stub(mock.count()).toReturn(10);

-     *

-     *   //You can do:

-     *   when(mock.count()).thenReturn(10);

-     * </code></pre>

-     * For stubbing void methods with throwables see: {@link Mockito#doThrow(Throwable)}

-     * <p>

-     * Stubbing can be overridden: for example common stubbing can go to fixture

-     * setup but the test methods can override it.

-     * Please note that overridding stubbing is a potential code smell that points out too much stubbing.

-     * <p>

-     * Once stubbed, the method will always return stubbed value regardless

-     * of how many times it is called.

-     * <p>

-     * Last stubbing is more important - when you stubbed the same method with

-     * the same arguments many times.

-     * <p>

-     * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.

-     * Let's say you've stubbed foo.bar().

-     * If your code cares what foo.bar() returns then something else breaks(often before even verify() gets executed).

-     * If your code doesn't care what get(0) returns then it should not be stubbed.

-     * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.

-     *

-     * @param methodCall

-     *            method call

-     * @return DeprecatedOngoingStubbing object to set stubbed value/exception

-     */

-    public static <T> DeprecatedOngoingStubbing<T> stub(T methodCall) {

-        return MOCKITO_CORE.stub(methodCall);

-    }

-

-    /**

-     * Enables stubbing methods. Use it when you want the mock to return particular value when particular method is called.

-     * <p>

-     * Simply put: "<b>When</b> the x method is called <b>then</b> return y".

-     * <p>

-     * <b>when() is a successor of deprecated {@link Mockito#stub(Object)}</b>

-     * <p>

-     * Examples:

-     *

-     * <pre class="code"><code class="java">

-     * <b>when</b>(mock.someMethod()).<b>thenReturn</b>(10);

-     *

-     * //you can use flexible argument matchers, e.g:

-     * when(mock.someMethod(<b>anyString()</b>)).thenReturn(10);

-     *

-     * //setting exception to be thrown:

-     * when(mock.someMethod("some arg")).thenThrow(new RuntimeException());

-     *

-     * //you can set different behavior for consecutive method calls.

-     * //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.

-     * when(mock.someMethod("some arg"))

-     *  .thenThrow(new RuntimeException())

-     *  .thenReturn("foo");

-     *

-     * //Alternative, shorter version for consecutive stubbing:

-     * when(mock.someMethod("some arg"))

-     *  .thenReturn("one", "two");

-     * //is the same as:

-     * when(mock.someMethod("some arg"))

-     *  .thenReturn("one")

-     *  .thenReturn("two");

-     *

-     * //shorter version for consecutive method calls throwing exceptions:

-     * when(mock.someMethod("some arg"))

-     *  .thenThrow(new RuntimeException(), new NullPointerException();

-     *

-     * </code></pre>

-     *

-     * For stubbing void methods with throwables see: {@link Mockito#doThrow(Throwable)}

-     * <p>

-     * Stubbing can be overridden: for example common stubbing can go to fixture

-     * setup but the test methods can override it.

-     * Please note that overridding stubbing is a potential code smell that points out too much stubbing.

-     * <p>

-     * Once stubbed, the method will always return stubbed value regardless

-     * of how many times it is called.

-     * <p>

-     * Last stubbing is more important - when you stubbed the same method with

-     * the same arguments many times.

-     * <p>

-     * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.

-     * Let's say you've stubbed <code>foo.bar()</code>.

-     * If your code cares what <code>foo.bar()</code> returns then something else breaks(often before even <code>verify()</code> gets executed).

-     * If your code doesn't care what <code>get(0)</code> returns then it should not be stubbed.

-     * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.

-     *

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     * @param methodCall method to be stubbed

-     * @return OngoingStubbing object used to stub fluently.

-     *         <strong>Do not</strong> create a reference to this returned object.

-     */

-    public static <T> OngoingStubbing<T> when(T methodCall) {

-        return MOCKITO_CORE.when(methodCall);

-    }

-

-    /**

-     * Verifies certain behavior <b>happened once</b>.

-     * <p>

-     * Alias to <code>verify(mock, times(1))</code> E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock).someMethod("some arg");

-     * </code></pre>

-     * Above is equivalent to:

-     * <pre class="code"><code class="java">

-     *   verify(mock, times(1)).someMethod("some arg");

-     * </code></pre>

-     * <p>

-     * Arguments passed are compared using <code>equals()</code> method.

-     * Read about {@link ArgumentCaptor} or {@link ArgumentMatcher} to find out other ways of matching / asserting arguments passed.

-     * <p>

-     * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.

-     * Let's say you've stubbed <code>foo.bar()</code>.

-     * If your code cares what <code>foo.bar()</code> returns then something else breaks(often before even <code>verify()</code> gets executed).

-     * If your code doesn't care what <code>get(0)</code> returns then it should not be stubbed.

-     * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.

-     *

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param mock to be verified

-     * @return mock object itself

-     */

-    public static <T> T verify(T mock) {

-        return MOCKITO_CORE.verify(mock, times(1));

-    }

-

-    /**

-     * Verifies certain behavior happened at least once / exact number of times / never. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, times(5)).someMethod("was called five times");

-     *

-     *   verify(mock, atLeast(2)).someMethod("was called at least two times");

-     *

-     *   //you can use flexible argument matchers, e.g:

-     *   verify(mock, atLeastOnce()).someMethod(<b>anyString()</b>);

-     * </code></pre>

-     *

-     * <b>times(1) is the default</b> and can be omitted

-     * <p>

-     * Arguments passed are compared using <code>equals()</code> method.

-     * Read about {@link ArgumentCaptor} or {@link ArgumentMatcher} to find out other ways of matching / asserting arguments passed.

-     * <p>

-     *

-     * @param mock to be verified

-     * @param mode times(x), atLeastOnce() or never()

-     *

-     * @return mock object itself

-     */

-    public static <T> T verify(T mock, VerificationMode mode) {

-        return MOCKITO_CORE.verify(mock, mode);

-    }

-

-    /**

-     * Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.

-     * Normally, you don't need to reset your mocks, just create new mocks for each test method.

-     * <p>

-     * Instead of <code>#reset()</code> please consider writing simple, small and focused test methods over lengthy, over-specified tests.

-     * <b>First potential code smell is <code>reset()</code> in the middle of the test method.</b> This probably means you're testing too much.

-     * Follow the whisper of your test methods: "Please keep us small & focused on single behavior".

-     * There are several threads about it on mockito mailing list.

-     * <p>

-     * The only reason we added <code>reset()</code> method is to

-     * make it possible to work with container-injected mocks.

-     * See issue 55 (<a href="http://code.google.com/p/mockito/issues/detail?id=55">here</a>)

-     * or FAQ (<a href="http://code.google.com/p/mockito/wiki/FAQ">here</a>).

-     * <p>

-     * <b>Don't harm yourself.</b> <code>reset()</code> in the middle of the test method is a code smell (you're probably testing too much).

-     * <pre class="code"><code class="java">

-     *   List mock = mock(List.class);

-     *   when(mock.size()).thenReturn(10);

-     *   mock.add(1);

-     *

-     *   reset(mock);

-     *   //at this point the mock forgot any interactions & stubbing

-     * </code></pre>

-     *

-     * @param <T> The Type of the mocks

-     * @param mocks to be reset

-     */

-    public static <T> void reset(T ... mocks) {

-        MOCKITO_CORE.reset(mocks);

-    }

-

-    /**

-     * Checks if any of given mocks has any unverified interaction.

-     * <p>

-     * You can use this method after you verified your mocks - to make sure that nothing

-     * else was invoked on your mocks.

-     * <p>

-     * See also {@link Mockito#never()} - it is more explicit and communicates the intent well.

-     * <p>

-     * Stubbed invocations (if called) are also treated as interactions.

-     * <p>

-     * A word of <b>warning</b>:

-     * Some users who did a lot of classic, expect-run-verify mocking tend to use <code>verifyNoMoreInteractions()</code> very often, even in every test method.

-     * <code>verifyNoMoreInteractions()</code> is not recommended to use in every test method.

-     * <code>verifyNoMoreInteractions()</code> is a handy assertion from the interaction testing toolkit. Use it only when it's relevant.

-     * Abusing it leads to overspecified, less maintainable tests. You can find further reading

-     * <a href="http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/">here</a>.

-     * <p>

-     * This method will also detect unverified invocations that occurred before the test method,

-     * for example: in <code>setUp()</code>, <code>&#064;Before</code> method or in constructor.

-     * Consider writing nice code that makes interactions only in test methods.

-     *

-     * <p>

-     * Example:

-     *

-     * <pre class="code"><code class="java">

-     * //interactions

-     * mock.doSomething();

-     * mock.doSomethingUnexpected();

-     *

-     * //verification

-     * verify(mock).doSomething();

-     *

-     * //following will fail because 'doSomethingUnexpected()' is unexpected

-     * verifyNoMoreInteractions(mock);

-     *

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param mocks to be verified

-     */

-    public static void verifyNoMoreInteractions(Object... mocks) {

-        MOCKITO_CORE.verifyNoMoreInteractions(mocks);

-    }

-

-    /**

-     * Verifies that no interactions happened on given mocks.

-     * <pre class="code"><code class="java">

-     *   verifyZeroInteractions(mockOne, mockTwo);

-     * </code></pre>

-     * This method will also detect invocations

-     * that occurred before the test method, for example: in <code>setUp()</code>, <code>&#064;Before</code> method or in constructor.

-     * Consider writing nice code that makes interactions only in test methods.

-     * <p>

-     * See also {@link Mockito#never()} - it is more explicit and communicates the intent well.

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param mocks to be verified

-     */

-    public static void verifyZeroInteractions(Object... mocks) {

-        MOCKITO_CORE.verifyNoMoreInteractions(mocks);

-    }

-

-    /**

-     * <pre class="code"><code class="java">

-     *   //Instead of:

-     *   stubVoid(mock).toThrow(e).on().someVoidMethod();

-     *

-     *   //Please do:

-     *   doThrow(e).when(mock).someVoidMethod();

-     * </code></pre>

-     *

-     * doThrow() replaces stubVoid() because of improved readability and consistency with the family of doAnswer() methods.

-     * <p>

-     * Originally, <code>stubVoid()</code> was used for stubbing void methods with exceptions. E.g:

-     *

-     * <pre class="code"><code class="java">

-     * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod();

-     *

-     * //you can stub with different behavior for consecutive calls.

-     * //Last stubbing (e.g. toReturn()) determines the behavior for further consecutive calls.

-     * stubVoid(mock)

-     *   .toThrow(new RuntimeException())

-     *   .toReturn()

-     *   .on().someMethod();

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @deprecated Use {@link Mockito#doThrow(Throwable)} method for stubbing voids

-     *

-     * @param mock

-     *            to stub

-     * @return stubbable object that allows stubbing with throwable

-     */

-    public static <T> VoidMethodStubbable<T> stubVoid(T mock) {

-        return MOCKITO_CORE.stubVoid(mock);

-    }

-

-    /**

-     * Use <code>doThrow()</code> when you want to stub the void method with an exception.

-     * <p>

-     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...

-     * <p>

-     * Example:

-     *

-     * <pre class="code"><code class="java">

-     *   doThrow(new RuntimeException()).when(mock).someVoidMethod();

-     * </code></pre>

-     *

-     * @param toBeThrown to be thrown when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    public static Stubber doThrow(Throwable toBeThrown) {

-        return MOCKITO_CORE.doAnswer(new ThrowsException(toBeThrown));

-    }

-

-    /**

-     * Use <code>doThrow()</code> when you want to stub the void method to throw exception of specified class.

-     * <p>

-     * A new exception instance will be created for each method invocation.

-     * <p>

-     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...

-     * <p>

-     * Example:

-     *

-     * <pre class="code"><code class="java">

-     *   doThrow(RuntimeException.class).when(mock).someVoidMethod();

-     * </code></pre>

-     *

-     * @param toBeThrown to be thrown when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     * @since 1.9.0

-     */

-    public static Stubber doThrow(Class<? extends Throwable> toBeThrown) {

-        return MOCKITO_CORE.doAnswer(new ThrowsExceptionClass(toBeThrown));

-    }

-

-

-    /**

-     * Use <code>doCallRealMethod()</code> when you want to call the real implementation of a method.

-     * <p>

-     * As usual you are going to read <b>the partial mock warning</b>:

-     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.

-     * How does partial mock fit into this paradigm? Well, it just doesn't...

-     * Partial mock usually means that the complexity has been moved to a different method on the same object.

-     * In most cases, this is not the way you want to design your application.

-     * <p>

-     * However, there are rare cases when partial mocks come handy:

-     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)

-     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.

-     * <p>

-     * See also javadoc {@link Mockito#spy(Object)} to find out more about partial mocks.

-     * <b>Mockito.spy() is a recommended way of creating partial mocks.</b>

-     * The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.

-     * <p>

-     * Example:

-     * <pre class="code"><code class="java">

-     *   Foo mock = mock(Foo.class);

-     *   doCallRealMethod().when(mock).someVoidMethod();

-     *

-     *   // this will call the real implementation of Foo.someVoidMethod()

-     *   mock.someVoidMethod();

-     * </code></pre>

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @return stubber - to select a method for stubbing

-     * @since 1.9.5

-     */

-    public static Stubber doCallRealMethod() {

-        return MOCKITO_CORE.doAnswer(new CallsRealMethods());

-    }

-

-    /**

-     * Use <code>doAnswer()</code> when you want to stub a void method with generic {@link Answer}.

-     * <p>

-     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...

-     * <p>

-     * Example:

-     *

-     * <pre class="code"><code class="java">

-     *  doAnswer(new Answer() {

-     *      public Object answer(InvocationOnMock invocation) {

-     *          Object[] args = invocation.getArguments();

-     *          Mock mock = invocation.getMock();

-     *          return null;

-     *      }})

-     *  .when(mock).someMethod();

-     * </code></pre>

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param answer to answer when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    public static Stubber doAnswer(Answer answer) {

-        return MOCKITO_CORE.doAnswer(answer);

-    }

-

-    /**

-     * Use <code>doNothing()</code> for setting void methods to do nothing. <b>Beware that void methods on mocks do nothing by default!</b>

-     * However, there are rare situations when doNothing() comes handy:

-     * <p>

-     * <ol>

-     * <li>Stubbing consecutive calls on a void method:

-     * <pre class="code"><code class="java">

-     *   doNothing().

-     *   doThrow(new RuntimeException())

-     *   .when(mock).someVoidMethod();

-     *

-     *   //does nothing the first time:

-     *   mock.someVoidMethod();

-     *

-     *   //throws RuntimeException the next time:

-     *   mock.someVoidMethod();

-     * </code></pre>

-     * </li>

-     * <li>When you spy real objects and you want the void method to do nothing:

-     * <pre class="code"><code class="java">

-     *   List list = new LinkedList();

-     *   List spy = spy(list);

-     *

-     *   //let's make clear() do nothing

-     *   doNothing().when(spy).clear();

-     *

-     *   spy.add("one");

-     *

-     *   //clear() does nothing, so the list still contains "one"

-     *   spy.clear();

-     * </code></pre>

-     * </li>

-     * </ol>

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @return stubber - to select a method for stubbing

-     */

-    public static Stubber doNothing() {

-        return MOCKITO_CORE.doAnswer(new DoesNothing());

-    }

-

-    /**

-     * Use <code>doReturn()</code> in those rare occasions when you cannot use {@link Mockito#when(Object)}.

-     * <p>

-     * <b>Beware that {@link Mockito#when(Object)} is always recommended for stubbing because it is argument type-safe

-     * and more readable</b> (especially when stubbing consecutive calls).

-     * <p>

-     * Here are those rare occasions when doReturn() comes handy:

-     * <p>

-     *

-     * <ol>

-     * <li>When spying real objects and calling real methods on a spy brings side effects

-     *

-     * <pre class="code"><code class="java">

-     *   List list = new LinkedList();

-     *   List spy = spy(list);

-     *

-     *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)

-     *   when(spy.get(0)).thenReturn("foo");

-     *

-     *   //You have to use doReturn() for stubbing:

-     *   doReturn("foo").when(spy).get(0);

-     * </code></pre>

-     * </li>

-     *

-     * <li>Overriding a previous exception-stubbing:

-     * <pre class="code"><code class="java">

-     *   when(mock.foo()).thenThrow(new RuntimeException());

-     *

-     *   //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.

-     *   when(mock.foo()).thenReturn("bar");

-     *

-     *   //You have to use doReturn() for stubbing:

-     *   doReturn("bar").when(mock).foo();

-     * </code></pre>

-     * </li>

-     * </ol>

-     *

-     * Above scenarios shows a tradeoff of Mockito's elegant syntax. Note that the scenarios are very rare, though.

-     * Spying should be sporadic and overriding exception-stubbing is very rare. Not to mention that in general

-     * overridding stubbing is a potential code smell that points out too much stubbing.

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param toBeReturned to be returned when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    public static Stubber doReturn(Object toBeReturned) {

-        return MOCKITO_CORE.doAnswer(new Returns(toBeReturned));

-    }

-

-    /**

-     * Creates {@link org.mockito.InOrder} object that allows verifying mocks in order.

-     *

-     * <pre class="code"><code class="java">

-     *   InOrder inOrder = inOrder(firstMock, secondMock);

-     *

-     *   inOrder.verify(firstMock).add("was called first");

-     *   inOrder.verify(secondMock).add("was called second");

-     * </code></pre>

-     *

-     * Verification in order is flexible - <b>you don't have to verify all interactions</b> one-by-one

-     * but only those that you are interested in testing in order.

-     * <p>

-     * Also, you can create InOrder object passing only mocks that are relevant for in-order verification.

-     * <p>

-     * <code>InOrder</code> verification is 'greedy'. You will hardly every notice it but

-     * if you want to find out more search for 'greedy' on the Mockito

-     * <a href="http://code.google.com/p/mockito/w/list">wiki pages</a>.

-     * <p>

-     * As of Mockito 1.8.4 you can verifyNoMoreInvocations() in order-sensitive way. Read more: {@link InOrder#verifyNoMoreInteractions()}

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param mocks to be verified in order

-     *

-     * @return InOrder object to be used to verify in order

-     */

-    public static InOrder inOrder(Object... mocks) {

-        return MOCKITO_CORE.inOrder(mocks);

-    }

-

-    /**

-     * Ignores stubbed methods of given mocks for the sake of verification.

-     * Sometimes useful when coupled with <code>verifyNoMoreInteractions()</code> or verification <code>inOrder()</code>.

-     * Helps avoiding redundant verification of stubbed calls - typically we're not interested in verifying stubs.

-     * <p>

-     * <b>Warning</b>, <code>ignoreStubs()</code> might lead to overuse of <code>verifyNoMoreInteractions(ignoreStubs(...));</code>

-     * Bear in mind that Mockito does not recommend bombarding every test with <code>verifyNoMoreInteractions()</code>

-     * for the reasons outlined in javadoc for {@link Mockito#verifyNoMoreInteractions(Object...)}

-     * Other words: all <b>*stubbed*</b> methods of given mocks are marked <b>*verified*</b> so that they don't get in a way during verifyNoMoreInteractions().

-     * <p>

-     * This method <b>changes the input mocks</b>! This method returns input mocks just for convenience.

-     * <p>

-     * Ignored stubs will also be ignored for verification inOrder, including {@link org.mockito.InOrder#verifyNoMoreInteractions()}.

-     * See the second example.

-     * <p>

-     * Example:

-     * <pre class="code"><code class="java">

-     *  //mocking lists for the sake of the example (if you mock List in real you will burn in hell)

-     *  List mock1 = mock(List.class), mock2 = mock(List.class);

-     *

-     *  //stubbing mocks:

-     *  when(mock1.get(0)).thenReturn(10);

-     *  when(mock2.get(0)).thenReturn(20);

-     *

-     *  //using mocks by calling stubbed get(0) methods:

-     *  System.out.println(mock1.get(0)); //prints 10

-     *  System.out.println(mock2.get(0)); //prints 20

-     *

-     *  //using mocks by calling clear() methods:

-     *  mock1.clear();

-     *  mock2.clear();

-     *

-     *  //verification:

-     *  verify(mock1).clear();

-     *  verify(mock2).clear();

-     *

-     *  //verifyNoMoreInteractions() fails because get() methods were not accounted for.

-     *  try { verifyNoMoreInteractions(mock1, mock2); } catch (NoInteractionsWanted e);

-     *

-     *  //However, if we ignore stubbed methods then we can verifyNoMoreInteractions()

-     *  verifyNoMoreInteractions(ignoreStubs(mock1, mock2));

-     *

-     *  //Remember that ignoreStubs() <b>*changes*</b> the input mocks and returns them for convenience.

-     * </code></pre>

-     * Ignoring stubs can be used with <b>verification in order</b>:

-     * <pre class="code"><code class="java">

-     *  List list = mock(List.class);

-     *  when(mock.get(0)).thenReturn("foo");

-     *

-     *  list.add(0);

-     *  System.out.println(list.get(0)); //we don't want to verify this

-     *  list.clear();

-     *

-     *  InOrder inOrder = inOrder(ignoreStubs(list));

-     *  inOrder.verify(list).add(0);

-     *  inOrder.verify(list).clear();

-     *  inOrder.verifyNoMoreInteractions();

-     * </code></pre>

-     *

-     * @since 1.9.0

-     * @param mocks input mocks that will be changed

-     * @return the same mocks that were passed in as parameters

-     */

-    public static Object[] ignoreStubs(Object... mocks) {

-        return MOCKITO_CORE.ignoreStubs(mocks);

-    }

-

-    /**

-     * Allows verifying exact number of invocations. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, times(2)).someMethod("some arg");

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param wantedNumberOfInvocations wanted number of invocations

-     *

-     * @return verification mode

-     */

-    public static VerificationMode times(int wantedNumberOfInvocations) {

-        return VerificationModeFactory.times(wantedNumberOfInvocations);

-    }

-

-    /**

-     * Alias to <code>times(0)</code>, see {@link Mockito#times(int)}

-     * <p>

-     * Verifies that interaction did not happen. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, never()).someMethod();

-     * </code></pre>

-     *

-     * <p>

-     * If you want to verify there were NO interactions with the mock

-     * check out {@link Mockito#verifyZeroInteractions(Object...)}

-     * or {@link Mockito#verifyNoMoreInteractions(Object...)}

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @return verification mode

-     */

-    public static VerificationMode never() {

-        return times(0);

-    }

-

-    /**

-     * Allows at-least-once verification. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, atLeastOnce()).someMethod("some arg");

-     * </code></pre>

-     * Alias to <code>atLeast(1)</code>.

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @return verification mode

-     */

-    public static VerificationMode atLeastOnce() {

-        return VerificationModeFactory.atLeastOnce();

-    }

-

-    /**

-     * Allows at-least-x verification. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, atLeast(3)).someMethod("some arg");

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param minNumberOfInvocations minimum number of invocations

-     *

-     * @return verification mode

-     */

-    public static VerificationMode atLeast(int minNumberOfInvocations) {

-        return VerificationModeFactory.atLeast(minNumberOfInvocations);

-    }

-

-    /**

-     * Allows at-most-x verification. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, atMost(3)).someMethod("some arg");

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param maxNumberOfInvocations max number of invocations

-     *

-     * @return verification mode

-     */

-    public static VerificationMode atMost(int maxNumberOfInvocations) {

-        return VerificationModeFactory.atMost(maxNumberOfInvocations);

-    }

-

-    /**

-     * Allows non-greedy verification in order.  For example

-     * <pre class="code"><code class="java">

-     *   inOrder.verify( mock, calls( 2 )).someMethod( "some arg" );

-     * </code></pre>

-     * <ul>

-     * <li>will not fail if the method is called 3 times, unlike times( 2 )</li>

-     * <li>will not mark the third invocation as verified, unlike atLeast( 2 )</li>

-     * </ul>

-     * This verification mode can only be used with in order verification.

-     * @param wantedNumberOfInvocations number of invocations to verify

-     * @return  verification mode

-     */

-    public static VerificationMode calls( int wantedNumberOfInvocations ){

-        return VerificationModeFactory.calls( wantedNumberOfInvocations );

-    }

-

-    /**

-     * Allows checking if given method was the only one invoked. E.g:

-     * <pre class="code"><code class="java">

-     *   verify(mock, only()).someMethod();

-     *   //above is a shorthand for following 2 lines of code:

-     *   verify(mock).someMethod();

-     *   verifyNoMoreInvocations(mock);

-     * </code></pre>

-     *

-     * <p>

-     * See also {@link Mockito#verifyNoMoreInteractions(Object...)}

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @return verification mode

-     */

-    public static VerificationMode only() {

-    	return VerificationModeFactory.only();

-    }

-

-    /**

-     * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired

-     * interaction rather than fails immediately if has not already happened. May be useful for testing in concurrent

-     * conditions.

-     * <p>

-     * This differs from {@link Mockito#after after()} in that after() will wait the full period, unless

-     * the final test result is known early (e.g. if a never() fails), whereas timeout() will stop early as soon

-     * as verification passes, producing different behaviour when used with times(2), for example, which can pass

-     * and then later fail. In that case, timeout would pass as soon as times(2) passes, whereas after would run until

-     * times(2) failed, and then fail.

-     * <p>

-     * It feels this feature should be used rarely - figure out a better way of testing your multi-threaded system

-     * <p>

-     * Not yet implemented to work with InOrder verification.

-     * <pre class="code"><code class="java">

-     *   //passes when someMethod() is called within given time span

-     *   verify(mock, timeout(100)).someMethod();

-     *   //above is an alias to:

-     *   verify(mock, timeout(100).times(1)).someMethod();

-     *

-     *   //passes as soon as someMethod() has been called 2 times before the given timeout

-     *   verify(mock, timeout(100).times(2)).someMethod();

-     *

-     *   //equivalent: this also passes as soon as someMethod() has been called 2 times before the given timeout

-     *   verify(mock, timeout(100).atLeast(2)).someMethod();

-     *

-     *   //verifies someMethod() within given time span using given verification mode

-     *   //useful only if you have your own custom verification modes.

-     *   verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param millis - time span in milliseconds

-     *

-     * @return verification mode

-     */

-    public static VerificationWithTimeout timeout(long millis) {

-        return new Timeout(millis, VerificationModeFactory.times(1));

-    }

-

-    /**

-     * Allows verifying over a given period. It causes a verify to wait for a specified period of time for a desired

-     * interaction rather than failing immediately if has not already happened. May be useful for testing in concurrent

-     * conditions.

-     * <p>

-     * This differs from {@link Mockito#timeout timeout()} in that after() will wait the full period, whereas timeout()

-     * will stop early as soon as verification passes, producing different behaviour when used with times(2), for example,

-     * which can pass and then later fail. In that case, timeout would pass as soon as times(2) passes, whereas after would

-     * run the full time, which point it will fail, as times(2) has failed.

-     * <p>

-     * It feels this feature should be used rarely - figure out a better way of testing your multi-threaded system

-     * <p>

-     * Not yet implemented to work with InOrder verification.

-     * <pre class="code"><code class="java">

-     *   //passes after 100ms, if someMethod() has only been called once at that time.

-     *   verify(mock, after(100)).someMethod();

-     *   //above is an alias to:

-     *   verify(mock, after(100).times(1)).someMethod();

-     *

-     *   //passes if someMethod() is called <b>*exactly*</b> 2 times after the given timespan

-     *   verify(mock, after(100).times(2)).someMethod();

-     *

-     *   //passes if someMethod() has not been called after the given timespan

-     *   verify(mock, after(100).never()).someMethod();

-     *

-     *   //verifies someMethod() after a given time span using given verification mode

-     *   //useful only if you have your own custom verification modes.

-     *   verify(mock, new After(100, yourOwnVerificationMode)).someMethod();

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito} class

-     *

-     * @param millis - time span in milliseconds

-     *

-     * @return verification mode

-     */

-    public static VerificationAfterDelay after(int millis) {

-        return new After(millis, VerificationModeFactory.times(1));

-    }

-

-    /**

-     * First of all, in case of any trouble, I encourage you to read the Mockito FAQ: <a href="http://code.google.com/p/mockito/wiki/FAQ">http://code.google.com/p/mockito/wiki/FAQ</a>

-     * <p>

-     * In case of questions you may also post to mockito mailing list: <a href="http://groups.google.com/group/mockito">http://groups.google.com/group/mockito</a>

-     * <p>

-     * <code>validateMockitoUsage()</code> <b>explicitly validates</b> the framework state to detect invalid use of Mockito.

-     * However, this feature is optional <b>because Mockito validates the usage all the time...</b> but there is a gotcha so read on.

-     * <p>

-     * Examples of incorrect use:

-     * <pre class="code"><code class="java">

-     * //Oops, thenReturn() part is missing:

-     * when(mock.get());

-     *

-     * //Oops, verified method call is inside verify() where it should be on the outside:

-     * verify(mock.execute());

-     *

-     * //Oops, missing method to verify:

-     * verify(mock);

-     * </code></pre>

-     *

-     * Mockito throws exceptions if you misuse it so that you know if your tests are written correctly.

-     * The gotcha is that Mockito does the validation <b>next time</b> you use the framework (e.g. next time you verify, stub, call mock etc.).

-     * But even though the exception might be thrown in the next test,

-     * the exception <b>message contains a navigable stack trace element</b> with location of the defect.

-     * Hence you can click and find the place where Mockito was misused.

-     * <p>

-     * Sometimes though, you might want to validate the framework usage explicitly.

-     * For example, one of the users wanted to put <code>validateMockitoUsage()</code> in his <code>&#064;After</code> method

-     * so that he knows immediately when he misused Mockito.

-     * Without it, he would have known about it not sooner than <b>next time</b> he used the framework.

-     * One more benefit of having <code>validateMockitoUsage()</code> in <code>&#064;After</code> is that jUnit runner and rule will always fail in the test method with defect

-     * whereas ordinary 'next-time' validation might fail the <b>next</b> test method.

-     * But even though JUnit might report next test as red, don't worry about it

-     * and just click at navigable stack trace element in the exception message to instantly locate the place where you misused mockito.

-     * <p>

-     * <b>Both built-in runner: {@link MockitoJUnitRunner} and rule: {@link MockitoRule}</b> do validateMockitoUsage() after each test method.

-     * <p>

-     * Bear in mind that <b>usually you don't have to <code>validateMockitoUsage()</code></b>

-     * and framework validation triggered on next-time basis should be just enough,

-     * mainly because of enhanced exception message with clickable location of defect.

-     * However, I would recommend validateMockitoUsage() if you already have sufficient test infrastructure

-     * (like your own runner or base class for all tests) because adding a special action to <code>&#064;After</code> has zero cost.

-     * <p>

-     * See examples in javadoc for {@link Mockito} class

-     */

-    public static void validateMockitoUsage() {

-        MOCKITO_CORE.validateMockitoUsage();

-    }

-

-    /**

-     * Allows mock creation with additional mock settings.

-     * <p>

-     * Don't use it too often.

-     * Consider writing simple tests that use simple mocks.

-     * Repeat after me: simple tests push simple, KISSy, readable & maintainable code.

-     * If you cannot write a test in a simple way - refactor the code under test.

-     * <p>

-     * Examples of mock settings:

-     * <pre class="code"><code class="java">

-     *   //Creates mock with different default answer & name

-     *   Foo mock = mock(Foo.class, withSettings()

-     *       .defaultAnswer(RETURNS_SMART_NULLS)

-     *       .name("cool mockie"));

-     *

-     *   //Creates mock with different default answer, descriptive name and extra interfaces

-     *   Foo mock = mock(Foo.class, withSettings()

-     *       .defaultAnswer(RETURNS_SMART_NULLS)

-     *       .name("cool mockie")

-     *       .extraInterfaces(Bar.class));

-     * </code></pre>

-     * {@link MockSettings} has been introduced for two reasons.

-     * Firstly, to make it easy to add another mock settings when the demand comes.

-     * Secondly, to enable combining different mock settings without introducing zillions of overloaded mock() methods.

-     * <p>

-     * See javadoc for {@link MockSettings} to learn about possible mock settings.

-     * <p>

-     *

-     * @return mock settings instance with defaults.

-     */

-    public static MockSettings withSettings() {

-        return new MockSettingsImpl().defaultAnswer(RETURNS_DEFAULTS);

-    }

-

-    /**

-     * Helps debugging failing tests. Experimental - use at your own risk. We're not sure if this method will stay in public api.

-     */

-    @Deprecated

-    static MockitoDebugger debug() {

-        return new MockitoDebuggerImpl();

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.debugging.MockitoDebuggerImpl;
+import org.mockito.internal.framework.DefaultMockitoFramework;
+import org.mockito.internal.session.DefaultMockitoSessionBuilder;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+import org.mockito.mock.SerializableMode;
+import org.mockito.quality.MockitoHint;
+import org.mockito.quality.Strictness;
+import org.mockito.session.MockitoSessionBuilder;
+import org.mockito.stubbing.*;
+import org.mockito.verification.*;
+
+/**
+ * <p align="left"><img src="logo.png" srcset="logo@2x.png 2x" alt="Mockito logo"/></p>
+ * The Mockito library enables mock creation, verification and stubbing.
+ *
+ * <p>
+ * This javadoc content is also available on the <a href="http://mockito.org">http://mockito.org</a> web page.
+ * All documentation is kept in javadocs because it guarantees consistency between what's on the web and what's in the source code.
+ * It allows access to documentation straight from the IDE even if you work offline.
+ * It motivates Mockito developers to keep documentation up-to-date with the code that they write,
+ * every day, with every commit.
+ *
+ * <h1>Contents</h1>
+ *
+ * <b>
+ *      <a href="#0">0. Migrating to Mockito 2</a><br/>
+ *      <a href="#0.1">0.1 Mockito Android support</a></br/>
+ *      <a href="#1">1. Let's verify some behaviour! </a><br/>
+ *      <a href="#2">2. How about some stubbing? </a><br/>
+ *      <a href="#3">3. Argument matchers </a><br/>
+ *      <a href="#4">4. Verifying exact number of invocations / at least once / never </a><br/>
+ *      <a href="#5">5. Stubbing void methods with exceptions </a><br/>
+ *      <a href="#6">6. Verification in order </a><br/>
+ *      <a href="#7">7. Making sure interaction(s) never happened on mock </a><br/>
+ *      <a href="#8">8. Finding redundant invocations </a><br/>
+ *      <a href="#9">9. Shorthand for mocks creation - <code>&#064;Mock</code> annotation </a><br/>
+ *      <a href="#10">10. Stubbing consecutive calls (iterator-style stubbing) </a><br/>
+ *      <a href="#11">11. Stubbing with callbacks </a><br/>
+ *      <a href="#12">12. <code>doReturn()</code>|<code>doThrow()</code>|<code>doAnswer()</code>|<code>doNothing()</code>|<code>doCallRealMethod()</code> family of methods</a><br/>
+ *      <a href="#13">13. Spying on real objects </a><br/>
+ *      <a href="#14">14. Changing default return values of unstubbed invocations (Since 1.7) </a><br/>
+ *      <a href="#15">15. Capturing arguments for further assertions (Since 1.8.0) </a><br/>
+ *      <a href="#16">16. Real partial mocks (Since 1.8.0) </a><br/>
+ *      <a href="#17">17. Resetting mocks (Since 1.8.0) </a><br/>
+ *      <a href="#18">18. Troubleshooting & validating framework usage (Since 1.8.0) </a><br/>
+ *      <a href="#19">19. Aliases for behavior driven development (Since 1.8.0) </a><br/>
+ *      <a href="#20">20. Serializable mocks (Since 1.8.1) </a><br/>
+ *      <a href="#21">21. New annotations: <code>&#064;Captor</code>, <code>&#064;Spy</code>, <code>&#064;InjectMocks</code> (Since 1.8.3) </a><br/>
+ *      <a href="#22">22. Verification with timeout (Since 1.8.5) </a><br/>
+ *      <a href="#23">23. Automatic instantiation of <code>&#064;Spies</code>, <code>&#064;InjectMocks</code> and constructor injection goodness (Since 1.9.0)</a><br/>
+ *      <a href="#24">24. One-liner stubs (Since 1.9.0)</a><br/>
+ *      <a href="#25">25. Verification ignoring stubs (Since 1.9.0)</a><br/>
+ *      <a href="#26">26. Mocking details (Improved in 2.2.x)</a><br/>
+ *      <a href="#27">27. Delegate calls to real instance (Since 1.9.5)</a><br/>
+ *      <a href="#28">28. <code>MockMaker</code> API (Since 1.9.5)</a><br/>
+ *      <a href="#29">29. BDD style verification (Since 1.10.0)</a><br/>
+ *      <a href="#30">30. Spying or mocking abstract classes (Since 1.10.12) and Java 8 default methods (Since release 2.x)</a><br/>
+ *      <a href="#31">31. Mockito mocks can be <em>serialized</em> / <em>deserialized</em> across classloaders (Since 1.10.0)</a></h3><br/>
+ *      <a href="#32">32. Better generic support with deep stubs (Since 1.10.0)</a></h3><br/>
+ *      <a href="#32">33. Mockito JUnit rule (Since 1.10.17)</a><br/>
+ *      <a href="#34">34. Switch <em>on</em> or <em>off</em> plugins (Since 1.10.15)</a><br/>
+ *      <a href="#35">35. Custom verification failure message (Since 2.1.0)</a><br/>
+ *      <a href="#36">36. Java 8 Lambda Matcher Support (Since 2.1.0)</a><br/>
+ *      <a href="#37">37. Java 8 Custom Answer Support (Since 2.1.0)</a><br/>
+ *      <a href="#38">38. Meta data and generic type retention (Since 2.1.0)</a><br/>
+ *      <a href="#39">39. Mocking final types, enums and final methods (Since 2.1.0)</a><br/>
+ *      <a href="#40">40. (**new**) Improved productivity and cleaner tests with "stricter" Mockito (Since 2.+)</a><br/>
+ * </b>
+ *
+ * <h3 id="0">0. <a class="meaningful_link" href="#mockito2" name="mockito2">Migrating to Mockito 2</a></h3>
+ *
+ * In order to continue improving Mockito and further improve the unit testing experience, we want you to upgrade to 2.1.0!
+ * Mockito follows <a href="http://semver.org/">semantic versioning</a> and contains breaking changes only on major version upgrades.
+ * In the lifecycle of a library, breaking changes are necessary
+ * to roll out a set of brand new features that alter the existing behavior or even change the API.
+ * For a comprehensive guide on the new release including incompatible changes,
+ * see '<a href="https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2">What's new in Mockito 2</a>' wiki page.
+ * We hope that you enjoy Mockito 2!
+ *
+ * <h3 id="0.1">0.1. <a class="meaningful_link" href="#mockito" name="mockito-android">Mockito Android support</a></h3>
+ *
+ * With Mockito version 2.6.1 we ship "native" Android support. To enable Android support, add the `mockito-android` library as dependency
+ * to your project. This artifact is published to the same Mockito organization and can be imported for Android as follows:
+ *
+ * <pre class="code"><code>
+ * repositories {
+ *   jcenter()
+ * }
+ * dependencies {
+ *   testCompile "org.mockito:mockito-core:+"
+ *   androidTestCompile "org.mockito:mockito-android:+"
+ * }
+ * </code></pre>
+ *
+ * You can continue to run the same unit tests on a regular VM by using the `mockito-core` artifact in your "testCompile" scope as shown
+ * above. Be aware that you cannot use the <a href="#39">inline mock maker</a> on Android due to limitations in the Android VM.
+ *
+ * If you encounter issues with mocking on Android, please open an issue
+ * <a href="https://github.com/mockito/mockito/issues/new">on the official issue tracker</a>.
+ * Do provide the version of Android you are working on and dependencies of your project.
+ *
+ * <h3 id="1">1. <a class="meaningful_link" href="#verification" name="verification">Let's verify some behaviour!</a></h3>
+ *
+ * The following examples mock a List, because most people are familiar with the interface (such as the
+ * <code>add()</code>, <code>get()</code>, <code>clear()</code> methods). <br>
+ * In reality, please don't mock the List class. Use a real instance instead.
+ *
+ * <pre class="code"><code class="java">
+ * //Let's import Mockito statically so that the code looks clearer
+ * import static org.mockito.Mockito.*;
+ *
+ * //mock creation
+ * List mockedList = mock(List.class);
+ *
+ * //using mock object
+ * mockedList.add("one");
+ * mockedList.clear();
+ *
+ * //verification
+ * verify(mockedList).add("one");
+ * verify(mockedList).clear();
+ * </code></pre>
+ *
+ * <p>
+ * Once created, a mock will remember all interactions. Then you can selectively
+ * verify whatever interactions you are interested in.
+ *
+ *
+ *
+ *
+ * <h3 id="2">2. <a class="meaningful_link" href="#stubbing" name="stubbing">How about some stubbing?</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //You can mock concrete classes, not just interfaces
+ * LinkedList mockedList = mock(LinkedList.class);
+ *
+ * //stubbing
+ * when(mockedList.get(0)).thenReturn("first");
+ * when(mockedList.get(1)).thenThrow(new RuntimeException());
+ *
+ * //following prints "first"
+ * System.out.println(mockedList.get(0));
+ *
+ * //following throws runtime exception
+ * System.out.println(mockedList.get(1));
+ *
+ * //following prints "null" because get(999) was not stubbed
+ * System.out.println(mockedList.get(999));
+ *
+ * //Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>
+ * //If your code cares what get(0) returns, then something else breaks (often even before verify() gets executed).
+ * //If your code doesn't care what get(0) returns, then it should not be stubbed. Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+ * verify(mockedList).get(0);
+ * </code></pre>
+ *
+ * <ul>
+ * <li> By default, for all methods that return a value, a mock will return either null, a
+ * a primitive/primitive wrapper value, or an empty collection, as appropriate.
+ * For example 0 for an int/Integer and false for a boolean/Boolean. </li>
+ *
+ * <li> Stubbing can be overridden: for example common stubbing can go to
+ * fixture setup but the test methods can override it.
+ * Please note that overridding stubbing is a potential code smell that points out too much stubbing</li>
+ *
+ * <li> Once stubbed, the method will always return a stubbed value, regardless
+ * of how many times it is called. </li>
+ *
+ * <li> Last stubbing is more important - when you stubbed the same method with
+ * the same arguments many times.
+ * Other words: <b>the order of stubbing matters</b> but it is only meaningful rarely,
+ * e.g. when stubbing exactly the same method calls or sometimes when argument matchers are used, etc.</li>
+ *
+ * </ul>
+ *
+ *
+ *
+ * <h3 id="3">3. <a class="meaningful_link" href="#argument_matchers" name="argument_matchers">Argument matchers</a></h3>
+ *
+ * Mockito verifies argument values in natural java style: by using an <code>equals()</code> method.
+ * Sometimes, when extra flexibility is required then you might use argument matchers:
+ *
+ * <pre class="code"><code class="java">
+ * //stubbing using built-in anyInt() argument matcher
+ * when(mockedList.get(anyInt())).thenReturn("element");
+ *
+ * //stubbing using custom matcher (let's say isValid() returns your own matcher implementation):
+ * when(mockedList.contains(argThat(isValid()))).thenReturn("element");
+ *
+ * //following prints "element"
+ * System.out.println(mockedList.get(999));
+ *
+ * //<b>you can also verify using an argument matcher</b>
+ * verify(mockedList).get(anyInt());
+ *
+ * //<b>argument matchers can also be written as Java 8 Lambdas</b>
+ * verify(mockedList).add(argThat(someString -> someString.length() > 5));
+ *
+ * </code></pre>
+ *
+ * <p>
+ * Argument matchers allow flexible verification or stubbing.
+ * {@link ArgumentMatchers Click here} {@link org.mockito.hamcrest.MockitoHamcrest or here} to see more built-in matchers
+ * and examples of <b>custom argument matchers / hamcrest matchers</b>.
+ * <p>
+ * For information solely on <b>custom argument matchers</b> check out javadoc for {@link ArgumentMatcher} class.
+ * <p>
+ * Be reasonable with using complicated argument matching.
+ * The natural matching style using <code>equals()</code> with occasional <code>anyX()</code> matchers tend to give clean & simple tests.
+ * Sometimes it's just better to refactor the code to allow <code>equals()</code> matching or even implement <code>equals()</code> method to help out with testing.
+ * <p>
+ * Also, read <a href="#15">section 15</a> or javadoc for {@link ArgumentCaptor} class.
+ * {@link ArgumentCaptor} is a special implementation of an argument matcher that captures argument values for further assertions.
+ * <p>
+ * <b>Warning on argument matchers:</b>
+ * <p>
+ * If you are using argument matchers, <b>all arguments</b> have to be provided
+ * by matchers.
+ * <p>
+ The following example shows verification but the same applies to stubbing:
+ *
+ * <pre class="code"><code class="java">
+ *   verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);
+ *   //above is correct - eq() is also an argument matcher
+ *
+ *   verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);
+ *   //above is incorrect - exception will be thrown because third argument is given without an argument matcher.
+ * </code></pre>
+ *
+ * <p>
+ * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.
+ * Internally, they record a matcher on a stack and return a dummy value (usually null).
+ * This implementation is due to static type safety imposed by the java compiler.
+ * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.
+ *
+ *
+ *
+ *
+ * <h3 id="4">4. <a class="meaningful_link" href="#exact_verification" name="exact_verification">Verifying exact number of invocations</a> /
+ * <a class="meaningful_link" href="#at_least_verification" name="at_least_verification">at least x</a> / never</h3>
+ *
+ * <pre class="code"><code class="java">
+ * //using mock
+ * mockedList.add("once");
+ *
+ * mockedList.add("twice");
+ * mockedList.add("twice");
+ *
+ * mockedList.add("three times");
+ * mockedList.add("three times");
+ * mockedList.add("three times");
+ *
+ * //following two verifications work exactly the same - times(1) is used by default
+ * verify(mockedList).add("once");
+ * verify(mockedList, times(1)).add("once");
+ *
+ * //exact number of invocations verification
+ * verify(mockedList, times(2)).add("twice");
+ * verify(mockedList, times(3)).add("three times");
+ *
+ * //verification using never(). never() is an alias to times(0)
+ * verify(mockedList, never()).add("never happened");
+ *
+ * //verification using atLeast()/atMost()
+ * verify(mockedList, atLeastOnce()).add("three times");
+ * verify(mockedList, atLeast(2)).add("five times");
+ * verify(mockedList, atMost(5)).add("three times");
+ *
+ * </code></pre>
+ *
+ * <p>
+ * <b>times(1) is the default.</b> Therefore using times(1) explicitly can be
+ * omitted.
+ *
+ *
+ *
+ *
+ * <h3 id="5">5. <a class="meaningful_link" href="#stubbing_with_exceptions" name="stubbing_with_exceptions">Stubbing void methods with exceptions</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ *   doThrow(new RuntimeException()).when(mockedList).clear();
+ *
+ *   //following throws RuntimeException:
+ *   mockedList.clear();
+ * </code></pre>
+ *
+ * Read more about <code>doThrow()</code>|<code>doAnswer()</code> family of methods in <a href="#12">section 12</a>.
+ * <p>
+ *
+ * <h3 id="6">6. <a class="meaningful_link" href="#in_order_verification" name="in_order_verification">Verification in order</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * // A. Single mock whose methods must be invoked in a particular order
+ * List singleMock = mock(List.class);
+ *
+ * //using a single mock
+ * singleMock.add("was added first");
+ * singleMock.add("was added second");
+ *
+ * //create an inOrder verifier for a single mock
+ * InOrder inOrder = inOrder(singleMock);
+ *
+ * //following will make sure that add is first called with "was added first, then with "was added second"
+ * inOrder.verify(singleMock).add("was added first");
+ * inOrder.verify(singleMock).add("was added second");
+ *
+ * // B. Multiple mocks that must be used in a particular order
+ * List firstMock = mock(List.class);
+ * List secondMock = mock(List.class);
+ *
+ * //using mocks
+ * firstMock.add("was called first");
+ * secondMock.add("was called second");
+ *
+ * //create inOrder object passing any mocks that need to be verified in order
+ * InOrder inOrder = inOrder(firstMock, secondMock);
+ *
+ * //following will make sure that firstMock was called before secondMock
+ * inOrder.verify(firstMock).add("was called first");
+ * inOrder.verify(secondMock).add("was called second");
+ *
+ * // Oh, and A + B can be mixed together at will
+ * </code></pre>
+ *
+ * Verification in order is flexible - <b>you don't have to verify all
+ * interactions</b> one-by-one but only those that you are interested in
+ * testing in order.
+ * <p>
+ * Also, you can create an InOrder object passing only the mocks that are relevant for
+ * in-order verification.
+ *
+ *
+ *
+ *
+ * <h3 id="7">7. <a class="meaningful_link" href="#never_verification" name="never_verification">Making sure interaction(s) never happened on mock</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //using mocks - only mockOne is interacted
+ * mockOne.add("one");
+ *
+ * //ordinary verification
+ * verify(mockOne).add("one");
+ *
+ * //verify that method was never called on a mock
+ * verify(mockOne, never()).add("two");
+ *
+ * //verify that other mocks were not interacted
+ * verifyZeroInteractions(mockTwo, mockThree);
+ *
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="8">8. <a class="meaningful_link" href="#finding_redundant_invocations" name="finding_redundant_invocations">Finding redundant invocations</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //using mocks
+ * mockedList.add("one");
+ * mockedList.add("two");
+ *
+ * verify(mockedList).add("one");
+ *
+ * //following verification will fail
+ * verifyNoMoreInteractions(mockedList);
+ * </code></pre>
+ *
+ * A word of <b>warning</b>:
+ * Some users who did a lot of classic, expect-run-verify mocking tend to use <code>verifyNoMoreInteractions()</code> very often, even in every test method.
+ * <code>verifyNoMoreInteractions()</code> is not recommended to use in every test method.
+ * <code>verifyNoMoreInteractions()</code> is a handy assertion from the interaction testing toolkit. Use it only when it's relevant.
+ * Abusing it leads to <strong>overspecified</strong>, <strong>less maintainable</strong> tests. You can find further reading
+ * <a href="http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/">here</a>.
+ *
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and
+ * communicates the intent well.
+ * <p>
+ *
+ *
+ *
+ *
+ * <h3 id="9">9. <a class="meaningful_link" href="#mock_annotation" name="mock_annotation">Shorthand for mocks creation - <code>&#064;Mock</code> annotation</a></h3>
+ *
+ * <ul>
+ * <li>Minimizes repetitive mock creation code.</li>
+ * <li>Makes the test class more readable.</li>
+ * <li>Makes the verification error easier to read because the <b>field name</b>
+ * is used to identify the mock.</li>
+ * </ul>
+ *
+ * <pre class="code"><code class="java">
+ *   public class ArticleManagerTest {
+ *
+ *       &#064;Mock private ArticleCalculator calculator;
+ *       &#064;Mock private ArticleDatabase database;
+ *       &#064;Mock private UserProvider userProvider;
+ *
+ *       private ArticleManager manager;
+ * </code></pre>
+ *
+ * <b>Important!</b> This needs to be somewhere in the base class or a test
+ * runner:
+ *
+ * <pre class="code"><code class="java">
+ * MockitoAnnotations.initMocks(testClass);
+ * </code></pre>
+ *
+ * You can use built-in runner: {@link MockitoJUnitRunner} or a rule: {@link MockitoRule}.
+ * <p>
+ * Read more here: {@link MockitoAnnotations}
+ *
+ *
+ *
+ *
+ * <h3 id="10">10. <a class="meaningful_link" href="#stubbing_consecutive_calls" name="stubbing_consecutive_calls">Stubbing consecutive calls</a> (iterator-style stubbing)</h3>
+ *
+ * Sometimes we need to stub with different return value/exception for the same
+ * method call. Typical use case could be mocking iterators.
+ * Original version of Mockito did not have this feature to promote simple mocking.
+ * For example, instead of iterators one could use {@link Iterable} or simply
+ * collections. Those offer natural ways of stubbing (e.g. using real
+ * collections). In rare scenarios stubbing consecutive calls could be useful,
+ * though:
+ * <p>
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod("some arg"))
+ *   .thenThrow(new RuntimeException())
+ *   .thenReturn("foo");
+ *
+ * //First call: throws runtime exception:
+ * mock.someMethod("some arg");
+ *
+ * //Second call: prints "foo"
+ * System.out.println(mock.someMethod("some arg"));
+ *
+ * //Any consecutive call: prints "foo" as well (last stubbing wins).
+ * System.out.println(mock.someMethod("some arg"));
+ * </code></pre>
+ *
+ * Alternative, shorter version of consecutive stubbing:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod("some arg"))
+ *   .thenReturn("one", "two", "three");
+ * </code></pre>
+ *
+ * <strong>Warning</strong> : if instead of chaining {@code .thenReturn()} calls, multiple stubbing with the same matchers or arguments
+ * is used, then each stubbing will override the previous one:
+ *
+ * <pre class="code"><code class="java">
+ * //All mock.someMethod("some arg") calls will return "two"
+ * when(mock.someMethod("some arg"))
+ *   .thenReturn("one")
+ * when(mock.someMethod("some arg"))
+ *   .thenReturn("two")
+ * </code></pre>
+ *
+ *
+ *
+ * <h3 id="11">11. <a class="meaningful_link" href="#answer_stubs" name="answer_stubs">Stubbing with callbacks</a></h3>
+ *
+ * Allows stubbing with generic {@link Answer} interface.
+ * <p>
+ * Yet another controversial feature which was not included in Mockito
+ * originally. We recommend simply stubbing with <code>thenReturn()</code> or
+ * <code>thenThrow()</code>, which should be enough to test/test-drive
+ * any clean & simple code. However, if you do have a need to stub with the generic Answer interface, here is an example:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer() {
+ *     Object answer(InvocationOnMock invocation) {
+ *         Object[] args = invocation.getArguments();
+ *         Object mock = invocation.getMock();
+ *         return "called with arguments: " + args;
+ *     }
+ * });
+ *
+ * //the following prints "called with arguments: foo"
+ * System.out.println(mock.someMethod("foo"));
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="12">12. <a class="meaningful_link" href="#do_family_methods_stubs" name="do_family_methods_stubs"><code>doReturn()</code>|<code>doThrow()</code>|
+ * <code>doAnswer()</code>|<code>doNothing()</code>|<code>doCallRealMethod()</code> family of methods</a></h3>
+ *
+ * Stubbing void methods requires a different approach from {@link Mockito#when(Object)} because the compiler does not
+ * like void methods inside brackets...
+ * <p>
+ * Use <code>doThrow()</code> when you want to stub a void method with an exception:
+ * <pre class="code"><code class="java">
+ *   doThrow(new RuntimeException()).when(mockedList).clear();
+ *
+ *   //following throws RuntimeException:
+ *   mockedList.clear();
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * You can use <code>doThrow()</code>, <code>doAnswer()</code>, <code>doNothing()</code>, <code>doReturn()</code>
+ * and <code>doCallRealMethod()</code> in place of the corresponding call with <code>when()</code>, for any method.
+ * It is necessary when you
+ * <ul>
+ *     <li>stub void methods</li>
+ *     <li>stub methods on spy objects (see below)</li>
+ *     <li>stub the same method more than once, to change the behaviour of a mock in the middle of a test.</li>
+ * </ul>
+ * but you may prefer to use these methods in place of the alternative with <code>when()</code>, for all of your stubbing calls.
+ * <p>
+ * Read more about these methods:
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ * {@link Mockito#doThrow(Throwable...)}
+ * <p>
+ * {@link Mockito#doThrow(Class)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doCallRealMethod()}
+ *
+ *
+ *
+ *
+ * <h3 id="13">13. <a class="meaningful_link" href="#spy" name="spy">Spying on real objects</a></h3>
+ *
+ * You can create spies of real objects. When you use the spy then the <b>real</b> methods are called
+ * (unless a method was stubbed).
+ * <p>
+ * Real spies should be used <b>carefully and occasionally</b>, for example when dealing with legacy code.
+ *
+ * <p>
+ * Spying on real objects can be associated with "partial mocking" concept.
+ * <b>Before the release 1.8</b>, Mockito spies were not real partial mocks.
+ * The reason was we thought partial mock is a code smell.
+ * At some point we found legitimate use cases for partial mocks
+ * (3rd party interfaces, interim refactoring of legacy code, the full article is
+ * <a href="http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring">here</a>)
+ * <p>
+ *
+ * <pre class="code"><code class="java">
+ *   List list = new LinkedList();
+ *   List spy = spy(list);
+ *
+ *   //optionally, you can stub out some methods:
+ *   when(spy.size()).thenReturn(100);
+ *
+ *   //using the spy calls <b>*real*</b> methods
+ *   spy.add("one");
+ *   spy.add("two");
+ *
+ *   //prints "one" - the first element of a list
+ *   System.out.println(spy.get(0));
+ *
+ *   //size() method was stubbed - 100 is printed
+ *   System.out.println(spy.size());
+ *
+ *   //optionally, you can verify
+ *   verify(spy).add("one");
+ *   verify(spy).add("two");
+ * </code></pre>
+ *
+ * <h4>Important gotcha on spying real objects!</h4>
+ * <ol>
+ * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.
+ * Therefore when using spies please consider <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code> family of
+ * methods for stubbing. Example:
+ *
+ * <pre class="code"><code class="java">
+ *   List list = new LinkedList();
+ *   List spy = spy(list);
+ *
+ *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ *   when(spy.get(0)).thenReturn("foo");
+ *
+ *   //You have to use doReturn() for stubbing
+ *   doReturn("foo").when(spy).get(0);
+ * </code></pre>
+ * </li>
+ *
+ * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.
+ * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction
+ * and their effect on real instance state.
+ * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,
+ * you won't see any effects on the real instance.
+ * </li>
+ *
+ * <li>Watch out for final methods.
+ * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.
+ * Also you won't be able to verify those method as well.
+ * </li>
+ * </ol>
+ *
+ *
+ *
+ *
+ * <h3 id="14">14. Changing <a class="meaningful_link" href="#defaultreturn" name="defaultreturn">default return values of unstubbed invocations</a> (Since 1.7)</h3>
+ *
+ * You can create a mock with specified strategy for its return values.
+ * It's quite an advanced feature and typically you don't need it to write decent tests.
+ * However, it can be helpful for working with <b>legacy systems</b>.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b> stub the method call.
+ *
+ * <pre class="code"><code class="java">
+ *   Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
+ *   Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+ * </code></pre>
+ *
+ * <p>
+ * Read more about this interesting implementation of <i>Answer</i>: {@link Mockito#RETURNS_SMART_NULLS}
+ *
+ *
+ *
+ *
+ * <h3 id="15">15. <a class="meaningful_link" href="#captors" name="captors">Capturing arguments</a> for further assertions (Since 1.8.0)</h3>
+ *
+ * Mockito verifies argument values in natural java style: by using an <code>equals()</code> method.
+ * This is also the recommended way of matching arguments because it makes tests clean & simple.
+ * In some situations though, it is helpful to assert on certain arguments after the actual verification.
+ * For example:
+ * <pre class="code"><code class="java">
+ *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);
+ *   verify(mock).doSomething(argument.capture());
+ *   assertEquals("John", argument.getValue().getName());
+ * </code></pre>
+ *
+ * <b>Warning:</b> it is recommended to use ArgumentCaptor with verification <b>but not</b> with stubbing.
+ * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
+ * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
+ * <p>
+ * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
+ * Both techniques can be used for making sure certain arguments where passed to mocks.
+ * However, ArgumentCaptor may be a better fit if:
+ * <ul>
+ * <li>custom argument matcher is not likely to be reused</li>
+ * <li>you just need it to assert on argument values to complete verification</li>
+ * </ul>
+ * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.
+ *
+ *
+ *
+ *
+ * <h3 id="16">16. <a class="meaningful_link" href="#partial_mocks" name="partial_mocks">Real partial mocks</a> (Since 1.8.0)</h3>
+ *
+ *  Finally, after many internal debates & discussions on the mailing list, partial mock support was added to Mockito.
+ *  Previously we considered partial mocks as code smells. However, we found a legitimate use case for partial mocks - more reading:
+ *  <a href="http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring">here</a>
+ *  <p>
+ *  <b>Before release 1.8</b> <code>spy()</code> was not producing real partial mocks and it was confusing for some users.
+ *  Read more about spying: <a href="#13">here</a> or in javadoc for {@link Mockito#spy(Object)} method.
+ *  <p>
+ *  <pre class="code"><code class="java">
+ *    //you can create partial mock with spy() method:
+ *    List list = spy(new LinkedList());
+ *
+ *    //you can enable partial mock capabilities selectively on mocks:
+ *    Foo mock = mock(Foo.class);
+ *    //Be sure the real implementation is 'safe'.
+ *    //If real implementation throws exceptions or depends on specific state of the object then you're in trouble.
+ *    when(mock.someMethod()).thenCallRealMethod();
+ *  </code></pre>
+ *
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ *
+ *
+ *
+ *
+ * <h3 id="17">17. <a class="meaningful_link" href="#resetting_mocks" name="resetting_mocks">Resetting mocks</a> (Since 1.8.0)</h3>
+ *
+ * Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.
+ * Normally, you don't need to reset your mocks, just create new mocks for each test method.
+ * <p>
+ * Instead of <code>reset()</code> please consider writing simple, small and focused test methods over lengthy, over-specified tests.
+ * <b>First potential code smell is <code>reset()</code> in the middle of the test method.</b> This probably means you're testing too much.
+ * Follow the whisper of your test methods: "Please keep us small & focused on single behavior".
+ * There are several threads about it on mockito mailing list.
+ * <p>
+ * The only reason we added <code>reset()</code> method is to
+ * make it possible to work with container-injected mocks.
+ * For more information see FAQ (<a href="https://github.com/mockito/mockito/wiki/FAQ">here</a>).
+ * <p>
+ * <b>Don't harm yourself.</b> <code>reset()</code> in the middle of the test method is a code smell (you're probably testing too much).
+ * <pre class="code"><code class="java">
+ *   List mock = mock(List.class);
+ *   when(mock.size()).thenReturn(10);
+ *   mock.add(1);
+ *
+ *   reset(mock);
+ *   //at this point the mock forgot any interactions & stubbing
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="18">18. <a class="meaningful_link" href="#framework_validation" name="framework_validation">Troubleshooting & validating framework usage</a> (Since 1.8.0)</h3>
+ *
+ * First of all, in case of any trouble, I encourage you to read the Mockito FAQ:
+ * <a href="https://github.com/mockito/mockito/wiki/FAQ">https://github.com/mockito/mockito/wiki/FAQ</a>
+ * <p>
+ * In case of questions you may also post to mockito mailing list:
+ * <a href="http://groups.google.com/group/mockito">http://groups.google.com/group/mockito</a>
+ * <p>
+ * Next, you should know that Mockito validates if you use it correctly <b>all the time</b>.
+ * However, there's a gotcha so please read the javadoc for {@link Mockito#validateMockitoUsage()}
+ *
+ *
+ *
+ *
+ * <h3 id="19">19. <a class="meaningful_link" href="#bdd_mockito" name="bdd_mockito">Aliases for behavior driven development</a> (Since 1.8.0)</h3>
+ *
+ * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.
+ * This is exactly how we write our tests and we warmly encourage you to do so!
+ * <p>
+ * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>
+ * <p>
+ * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.
+ * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.
+ * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.
+ * Now it really nicely integrates with the <b>given</b> component of a BDD style test!
+ * <p>
+ * Here is how the test might look like:
+ * <pre class="code"><code class="java">
+ * import static org.mockito.BDDMockito.*;
+ *
+ * Seller seller = mock(Seller.class);
+ * Shop shop = new Shop(seller);
+ *
+ * public void shouldBuyBread() throws Exception {
+ *   //given
+ *   given(seller.askForBread()).willReturn(new Bread());
+ *
+ *   //when
+ *   Goods goods = shop.buyBread();
+ *
+ *   //then
+ *   assertThat(goods, containBread());
+ * }
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="20">20. <a class="meaningful_link" href="#serializable_mocks" name="serializable_mocks">Serializable mocks</a> (Since 1.8.1)</h3>
+ *
+ * Mocks can be made serializable. With this feature you can use a mock in a place that requires dependencies to be serializable.
+ * <p>
+ * WARNING: This should be rarely used in unit testing.
+ * <p>
+ * The behaviour was implemented for a specific use case of a BDD spec that had an unreliable external dependency.  This
+ * was in a web environment and the objects from the external dependency were being serialized to pass between layers.
+ * <p>
+ * To create serializable mock use {@link MockSettings#serializable()}:
+ * <pre class="code"><code class="java">
+ *   List serializableMock = mock(List.class, withSettings().serializable());
+ * </code></pre>
+ * <p>
+ * The mock can be serialized assuming all the normal <a href='http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html'>
+ * serialization requirements</a> are met by the class.
+ * <p>
+ * Making a real object spy serializable is a bit more effort as the spy(...) method does not have an overloaded version
+ * which accepts MockSettings. No worries, you will hardly ever use it.
+ *
+ * <pre class="code"><code class="java">
+ * List&lt;Object&gt; list = new ArrayList&lt;Object&gt;();
+ * List&lt;Object&gt; spy = mock(ArrayList.class, withSettings()
+ *                 .spiedInstance(list)
+ *                 .defaultAnswer(CALLS_REAL_METHODS)
+ *                 .serializable());
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="21">21. New annotations: <a class="meaningful_link" href="#captor_annotation" name="captor_annotation"><code>&#064;Captor</code></a>,
+ * <a class="meaningful_link" href="#spy_annotation" name="spy_annotation"><code>&#064;Spy</code></a>,
+ * <a class="meaningful_link" href="#injectmocks_annotation" name="injectmocks_annotation"><code>&#064;InjectMocks</code></a> (Since 1.8.3)</h3>
+ *
+ * <p>
+ * Release 1.8.3 brings new annotations that may be helpful on occasion:
+ *
+ * <ul>
+ * <li>&#064;{@link Captor} simplifies creation of {@link ArgumentCaptor}
+ * - useful when the argument to capture is a nasty generic class and you want to avoid compiler warnings
+ * <li>&#064;{@link Spy} - you can use it instead {@link Mockito#spy(Object)}.
+ * <li>&#064;{@link InjectMocks} - injects mock or spy fields into tested object automatically.
+ * </ul>
+ *
+ * <p>
+ * Note that &#064;{@link InjectMocks} can also be used in combination with the &#064;{@link Spy} annotation, it means
+ * that Mockito will inject mocks into the partial mock under test. This complexity is another good reason why you
+ * should only use partial mocks as a last resort. See point 16 about partial mocks.
+ *
+ * <p>
+ * All new annotations are <b>*only*</b> processed on {@link MockitoAnnotations#initMocks(Object)}.
+ * Just like for &#064;{@link Mock} annotation you can use the built-in runner: {@link MockitoJUnitRunner} or rule:
+ * {@link MockitoRule}.
+ * <p>
+ *
+ *
+ *
+ *
+ * <h3 id="22">22. <a class="meaningful_link" href="#verification_timeout" name="verification_timeout">Verification with timeout</a> (Since 1.8.5)</h3>
+ * <p>
+ * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired
+ * interaction rather than fails immediately if had not already happened. May be useful for testing in concurrent
+ * conditions.
+ * <p>
+ * This feature should be used rarely - figure out a better way of testing your multi-threaded system.
+ * <p>
+ * Not yet implemented to work with InOrder verification.
+ * <p>
+ * Examples:
+ * <p>
+ * <pre class="code"><code class="java">
+ *   //passes when someMethod() is called within given time span
+ *   verify(mock, timeout(100)).someMethod();
+ *   //above is an alias to:
+ *   verify(mock, timeout(100).times(1)).someMethod();
+ *
+ *   //passes when someMethod() is called <b>*exactly*</b> 2 times within given time span
+ *   verify(mock, timeout(100).times(2)).someMethod();
+ *
+ *   //passes when someMethod() is called <b>*at least*</b> 2 times within given time span
+ *   verify(mock, timeout(100).atLeast(2)).someMethod();
+ *
+ *   //verifies someMethod() within given time span using given verification mode
+ *   //useful only if you have your own custom verification modes.
+ *   verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="23">23. <a class="meaningful_link" href="#automatic_instantiation" name="automatic_instantiation">Automatic instantiation of <code>&#064;Spies</code>,
+ * <code>&#064;InjectMocks</code></a> and <a class="meaningful_link" href="#constructor_injection" name="constructor_injection">constructor injection goodness</a> (Since 1.9.0)</h3>
+ *
+ * <p>
+ * Mockito will now try to instantiate &#064;{@link Spy} and will instantiate &#064;{@link InjectMocks} fields
+ * using <b>constructor</b> injection, <b>setter</b> injection, or <b>field</b> injection.
+ * <p>
+ * To take advantage of this feature you need to use {@link MockitoAnnotations#initMocks(Object)}, {@link MockitoJUnitRunner}
+ * or {@link MockitoRule}.
+ * <p>
+ * Read more about available tricks and the rules of injection in the javadoc for {@link InjectMocks}
+ * <pre class="code"><code class="java">
+ * //instead:
+ * &#064;Spy BeerDrinker drinker = new BeerDrinker();
+ * //you can write:
+ * &#064;Spy BeerDrinker drinker;
+ *
+ * //same applies to &#064;InjectMocks annotation:
+ * &#064;InjectMocks LocalPub;
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="24">24. <a class="meaningful_link" href="#one_liner_stub" name="one_liner_stub">One-liner stubs</a> (Since 1.9.0)</h3>
+ * <p>
+ * Mockito will now allow you to create mocks when stubbing.
+ * Basically, it allows to create a stub in one line of code.
+ * This can be helpful to keep test code clean.
+ * For example, some boring stub can be created & stubbed at field initialization in a test:
+ * <pre class="code"><code class="java">
+ * public class CarTest {
+ *   Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();
+ *
+ *   &#064;Test public void should... {}
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="25">25. <a class="meaningful_link" href="#ignore_stubs_verification" name="ignore_stubs_verification">Verification ignoring stubs</a> (Since 1.9.0)</h3>
+ * <p>
+ * Mockito will now allow to ignore stubbing for the sake of verification.
+ * Sometimes useful when coupled with <code>verifyNoMoreInteractions()</code> or verification <code>inOrder()</code>.
+ * Helps avoiding redundant verification of stubbed calls - typically we're not interested in verifying stubs.
+ * <p>
+ * <b>Warning</b>, <code>ignoreStubs()</code> might lead to overuse of verifyNoMoreInteractions(ignoreStubs(...));
+ * Bear in mind that Mockito does not recommend bombarding every test with <code>verifyNoMoreInteractions()</code>
+ * for the reasons outlined in javadoc for {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * <p>Some examples:
+ * <pre class="code"><code class="java">
+ * verify(mock).foo();
+ * verify(mockTwo).bar();
+ *
+ * //ignores all stubbed methods:
+ * verifyNoMoreInteractions(ignoreStubs(mock, mockTwo));
+ *
+ * //creates InOrder that will ignore stubbed
+ * InOrder inOrder = inOrder(ignoreStubs(mock, mockTwo));
+ * inOrder.verify(mock).foo();
+ * inOrder.verify(mockTwo).bar();
+ * inOrder.verifyNoMoreInteractions();
+ * </code></pre>
+ * <p>
+ * Advanced examples and more details can be found in javadoc for {@link Mockito#ignoreStubs(Object...)}
+ *
+ *
+ *
+ *
+ * <h3 id="26">26. <a class="meaningful_link" href="#mocking_details" name="mocking_details">Mocking details</a> (Improved in 2.2.x)</h3>
+ * <p>
+ *
+ * Mockito offers API to inspect the details of a mock object.
+ * This API is useful for advanced users and mocking framework integrators.
+ *
+ * <pre class="code"><code class="java">
+ *   //To identify whether a particular object is a mock or a spy:
+ *   Mockito.mockingDetails(someObject).isMock();
+ *   Mockito.mockingDetails(someObject).isSpy();
+ *
+ *   //Getting details like type to mock or default answer:
+ *   MockingDetails details = mockingDetails(mock);
+ *   details.getMockCreationSettings().getTypeToMock();
+ *   details.getMockCreationSettings().getDefaultAnswer();
+ *
+ *   //Getting interactions and stubbings of the mock:
+ *   MockingDetails details = mockingDetails(mock);
+ *   details.getInteractions();
+ *   details.getStubbings();
+ *
+ *   //Printing all interactions (including stubbing, unused stubs)
+ *   System.out.println(mockingDetails(mock).printInvocations());
+ * </code></pre>
+ *
+ * For more information see javadoc for {@link MockingDetails}.
+ *
+ * <h3 id="27">27. <a class="meaningful_link" href="#delegating_call_to_real_instance" name="delegating_call_to_real_instance">Delegate calls to real instance</a> (Since 1.9.5)</h3>
+ *
+ * <p>Useful for spies or partial mocks of objects <strong>that are difficult to mock or spy</strong> using the usual spy API.
+ * Since Mockito 1.10.11, the delegate may or may not be of the same type as the mock.
+ * If the type is different, a matching method needs to be found on delegate type otherwise an exception is thrown.
+ *
+ * Possible use cases for this feature:
+ * <ul>
+ *     <li>Final classes but with an interface</li>
+ *     <li>Already custom proxied object</li>
+ *     <li>Special objects with a finalize method, i.e. to avoid executing it 2 times</li>
+ * </ul>
+ *
+ * <p>The difference with the regular spy:
+ * <ul>
+ *   <li>
+ *     The regular spy ({@link #spy(Object)}) contains <strong>all</strong> state from the spied instance
+ *     and the methods are invoked on the spy. The spied instance is only used at mock creation to copy the state from.
+ *     If you call a method on a regular spy and it internally calls other methods on this spy, those calls are remembered
+ *     for verifications, and they can be effectively stubbed.
+ *   </li>
+ *   <li>
+ *     The mock that delegates simply delegates all methods to the delegate.
+ *     The delegate is used all the time as methods are delegated onto it.
+ *     If you call a method on a mock that delegates and it internally calls other methods on this mock,
+ *     those calls are <strong>not</strong> remembered for verifications, stubbing does not have effect on them, too.
+ *     Mock that delegates is less powerful than the regular spy but it is useful when the regular spy cannot be created.
+ *   </li>
+ * </ul>
+ *
+ * <p>
+ * See more information in docs for {@link AdditionalAnswers#delegatesTo(Object)}.
+ *
+ *
+ *
+ *
+ * <h3 id="28">28. <a class="meaningful_link" href="#mock_maker_plugin" name="mock_maker_plugin"><code>MockMaker</code> API</a> (Since 1.9.5)</h3>
+ * <p>Driven by requirements and patches from Google Android guys Mockito now offers an extension point
+ *   that allows replacing the proxy generation engine. By default, Mockito uses <a href="https://github.com/raphw/byte-buddy">Byte Buddy</a>
+ *   to create dynamic proxies.
+ * <p>The extension point is for advanced users that want to extend Mockito. For example, it is now possible
+ *   to use Mockito for Android testing with a help of <a href="https://github.com/crittercism/dexmaker">dexmaker</a>.
+ * <p>For more details, motivations and examples please refer to
+ * the docs for {@link org.mockito.plugins.MockMaker}.
+ *
+ *
+ *
+ *
+ * <h3 id="29">29. <a class="meaningful_link" href="#BDD_behavior_verification" name="BDD_behavior_verification">BDD style verification</a> (Since 1.10.0)</h3>
+ *
+ * Enables Behavior Driven Development (BDD) style verification by starting verification with the BDD <b>then</b> keyword.
+ *
+ * <pre class="code"><code class="java">
+ * given(dog.bark()).willReturn(2);
+ *
+ * // when
+ * ...
+ *
+ * then(person).should(times(2)).ride(bike);
+ * </code></pre>
+ *
+ * For more information and an example see {@link BDDMockito#then(Object)}}
+ *
+ *
+ *
+ *
+ * <h3 id="30">30. <a class="meaningful_link" href="#spying_abstract_classes" name="spying_abstract_classes">Spying or mocking abstract classes (Since 1.10.12) and Java 8 default methods (Since release 2.x)</a></h3>
+ *
+ * It is now possible to conveniently spy on abstract classes. Note that overusing spies hints at code design smells (see {@link #spy(Object)}).
+ * <p>
+ * Previously, spying was only possible on instances of objects.
+ * New API makes it possible to use constructor when creating an instance of the mock.
+ * This is particularly useful for mocking abstract classes because the user is no longer required to provide an instance of the abstract class.
+ * At the moment, only parameter-less constructor is supported, let us know if it is not enough.
+ *
+ * <pre class="code"><code class="java">
+ * //convenience API, new overloaded spy() method:
+ * SomeAbstract spy = spy(SomeAbstract.class);
+ *
+ * // Mocking abstract methods, spying default methods of an interface
+ * Function<Foo, Bar> function = spy(Function.class);
+ *
+ * //Robust API, via settings builder:
+ * OtherAbstract spy = mock(OtherAbstract.class, withSettings()
+ *    .useConstructor().defaultAnswer(CALLS_REAL_METHODS));
+ *
+ * //Mocking a non-static inner abstract class:
+ * InnerAbstract spy = mock(InnerAbstract.class, withSettings()
+ *    .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));
+ * </code></pre>
+ *
+ * For more information please see {@link MockSettings#useConstructor()}.
+ *
+ *
+ *
+ *
+ * <h3 id="31">31. <a class="meaningful_link" href="#serilization_across_classloader" name="serilization_across_classloader">Mockito mocks can be <em>serialized</em> / <em>deserialized</em> across classloaders (Since 1.10.0)</a></h3>
+ *
+ * Mockito introduces serialization across classloader.
+ *
+ * Like with any other form of serialization, all types in the mock hierarchy have to serializable, inclusing answers.
+ * As this serialization mode require considerably more work, this is an opt-in setting.
+ *
+ * <pre class="code"><code class="java">
+ * // use regular serialization
+ * mock(Book.class, withSettings().serializable());
+ *
+ * // use serialization across classloaders
+ * mock(Book.class, withSettings().serializable(ACROSS_CLASSLOADERS));
+ * </code></pre>
+ *
+ * For more details see {@link MockSettings#serializable(SerializableMode)}.
+ *
+ *
+ *
+ *
+ * <h3 id="32">32. <a class="meaningful_link" href="#better_generic_support_with_deep_stubs" name="better_generic_support_with_deep_stubs">Better generic support with deep stubs (Since 1.10.0)</a></h3>
+ *
+ * Deep stubbing has been improved to find generic information if available in the class.
+ * That means that classes like this can be used without having to mock the behavior.
+ *
+ * <pre class="code"><code class="java">
+ * class Lines extends List&lt;Line&gt; {
+ *     // ...
+ * }
+ *
+ * lines = mock(Lines.class, RETURNS_DEEP_STUBS);
+ *
+ * // Now Mockito understand this is not an Object but a Line
+ * Line line = lines.iterator().next();
+ * </code></pre>
+ *
+ * Please note that in most scenarios a mock returning a mock is wrong.
+ *
+ *
+ *
+ *
+ * <h3 id="33">33. <a class="meaningful_link" href="#mockito_junit_rule" name="mockito_junit_rule">Mockito JUnit rule (Since 1.10.17)</a></h3>
+ *
+ * Mockito now offers a JUnit rule. Until now in JUnit there were two ways to initialize fields annotated by Mockito annotations
+ * such as <code>&#064;{@link Mock}</code>, <code>&#064;{@link Spy}</code>, <code>&#064;{@link InjectMocks}</code>, etc.
+ *
+ * <ul>
+ *     <li>Annotating the JUnit test class with a <code>&#064;{@link org.junit.runner.RunWith}({@link MockitoJUnitRunner}.class)</code></li>
+ *     <li>Invoking <code>{@link MockitoAnnotations#initMocks(Object)}</code> in the <code>&#064;{@link org.junit.Before}</code> method</li>
+ * </ul>
+ *
+ * Now you can choose to use a rule :
+ *
+ * <pre class="code"><code class="java">
+ * &#064;RunWith(YetAnotherRunner.class)
+ * public class TheTest {
+ *     &#064;Rule public MockitoRule mockito = MockitoJUnit.rule();
+ *     // ...
+ * }
+ * </code></pre>
+ *
+ * For more information see {@link MockitoJUnit#rule()}.
+ *
+ *
+ *
+ *
+ * <h3 id="34">34. <a class="meaningful_link" href="#plugin_switch" name="plugin_switch">Switch <em>on</em> or <em>off</em> plugins (Since 1.10.15)</a></h3>
+ *
+ * An incubating feature made it's way in mockito that will allow to toggle a mockito-plugin.
+ *
+ * More information here {@link org.mockito.plugins.PluginSwitch}.
+ *
+ *
+ * <h3 id="35">35. <a class="meaningful_link" href="#BDD_behavior_verification" name="BDD_behavior_verification">Custom verification failure message</a> (Since 2.1.0)</h3>
+ * <p>
+ * Allows specifying a custom message to be printed if verification fails.
+ * <p>
+ * Examples:
+ * <p>
+ * <pre class="code"><code class="java">
+ *
+ * // will print a custom message on verification failure
+ * verify(mock, description("This will print on failure")).someMethod();
+ *
+ * // will work with any verification mode
+ * verify(mock, times(2).description("someMethod should be called twice")).someMethod();
+ * </code></pre>
+ *
+ * <h3 id="36">36. <a class="meaningful_link" href="#Java_8_Lambda_Matching" name="Java_8_Lambda_Matching">Java 8 Lambda Matcher Support</a> (Since 2.1.0)</h3>
+ * <p>
+ * You can use Java 8 lambda expressions with {@link ArgumentMatcher} to reduce the dependency on {@link ArgumentCaptor}.
+ * If you need to verify that the input to a function call on a mock was correct, then you would normally
+ * use the {@link ArgumentCaptor} to find the operands used and then do subsequent assertions on them. While
+ * for complex examples this can be useful, it's also long-winded.<p>
+ * Writing a lambda to express the match is quite easy. The argument to your function, when used in conjunction
+ * with argThat, will be passed to the ArgumentMatcher as a strongly typed object, so it is possible
+ * to do anything with it.
+ * <p>
+ * Examples:
+ * <p>
+ * <pre class="code"><code class="java">
+ *
+ * // verify a list only had strings of a certain length added to it
+ * // note - this will only compile under Java 8
+ * verify(list, times(2)).add(argThat(string -> string.length() < 5));
+ *
+ * // Java 7 equivalent - not as neat
+ * verify(list, times(2)).add(argThat(new ArgumentMatcher<String>(){
+ *     public boolean matches(String arg) {
+ *         return arg.length() < 5;
+ *     }
+ * }));
+ *
+ * // more complex Java 8 example - where you can specify complex verification behaviour functionally
+ * verify(target, times(1)).receiveComplexObject(argThat(obj -> obj.getSubObject().get(0).equals("expected")));
+ *
+ * // this can also be used when defining the behaviour of a mock under different inputs
+ * // in this case if the input list was fewer than 3 items the mock returns null
+ * when(mock.someMethod(argThat(list -> list.size()<3))).willReturn(null);
+ * </code></pre>
+ *
+ * <h3 id="37">37. <a class="meaningful_link" href="#Java_8_Custom_Answers" name="Java_8_Custom_Answers">Java 8 Custom Answer Support</a> (Since 2.1.0)</h3>
+ * <p>
+ * As the {@link Answer} interface has just one method it is already possible to implement it in Java 8 using
+ * a lambda expression for very simple situations. The more you need to use the parameters of the method call,
+ * the more you need to typecast the arguments from {@link org.mockito.invocation.InvocationOnMock}.
+ *
+ * <p>
+ * Examples:
+ * <p>
+ * <pre class="code"><code class="java">
+ * // answer by returning 12 every time
+ * doAnswer(invocation -> 12).when(mock).doSomething();
+ *
+ * // answer by using one of the parameters - converting into the right
+ * // type as your go - in this case, returning the length of the second string parameter
+ * // as the answer. This gets long-winded quickly, with casting of parameters.
+ * doAnswer(invocation -> ((String)invocation.getArgument(1)).length())
+ *     .when(mock).doSomething(anyString(), anyString(), anyString());
+ * </code></pre>
+ *
+ * For convenience it is possible to write custom answers/actions, which use the parameters to the method call,
+ * as Java 8 lambdas. Even in Java 7 and lower these custom answers based on a typed interface can reduce boilerplate.
+ * In particular, this approach will make it easier to test functions which use callbacks.
+ *
+ * The methods {@link AdditionalAnswers#answer(Answer1) answer} and {@link AdditionalAnswers#answerVoid(VoidAnswer1) answerVoid}
+ * can be used to create the answer. They rely on the related answer interfaces in {@link org.mockito.stubbing} that
+ * support answers up to 5 parameters.
+ *
+ * <p>
+ * Examples:
+ * <p>
+ * <pre class="code"><code class="java">
+ *
+ * // Example interface to be mocked has a function like:
+ * void execute(String operand, Callback callback);
+ *
+ * // the example callback has a function and the class under test
+ * // will depend on the callback being invoked
+ * void receive(String item);
+ *
+ * // Java 8 - style 1
+ * doAnswer(AdditionalAnswers.<String,Callback>answerVoid((operand, callback) -> callback.receive("dummy"))
+ *     .when(mock).execute(anyString(), any(Callback.class));
+ *
+ * // Java 8 - style 2 - assuming static import of AdditionalAnswers
+ * doAnswer(answerVoid((String operand, Callback callback) -> callback.receive("dummy"))
+ *     .when(mock).execute(anyString(), any(Callback.class));
+ *
+ * // Java 8 - style 3 - where mocking function to is a static member of test class
+ * private static void dummyCallbackImpl(String operation, Callback callback) {
+ *     callback.receive("dummy");
+ * }
+ *
+ * doAnswer(answerVoid(TestClass::dummyCallbackImpl)
+ *     .when(mock).execute(anyString(), any(Callback.class));
+ *
+ * // Java 7
+ * doAnswer(answerVoid(new VoidAnswer2<String, Callback>() {
+ *     public void answer(String operation, Callback callback) {
+ *         callback.receive("dummy");
+ *     }})).when(mock).execute(anyString(), any(Callback.class));
+ *
+ * // returning a value is possible with the answer() function
+ * // and the non-void version of the functional interfaces
+ * // so if the mock interface had a method like
+ * boolean isSameString(String input1, String input2);
+ *
+ * // this could be mocked
+ * // Java 8
+ * doAnswer(AdditionalAnswers.<Boolean,String,String>answer((input1, input2) -> input1.equals(input2))))
+ *     .when(mock).execute(anyString(), anyString());
+ *
+ * // Java 7
+ * doAnswer(answer(new Answer2<String, String, String>() {
+ *     public String answer(String input1, String input2) {
+ *         return input1 + input2;
+ *     }})).when(mock).execute(anyString(), anyString());
+ * </code></pre>
+ *
+ * <h3 id="38">38. <a class="meaningful_link" href="#Meta_Data_And_Generics" name="Meta_Data_And_Generics">Meta data and generic type retention</a> (Since 2.1.0)</h3>
+ *
+ * <p>
+ * Mockito now preserves annotations on mocked methods and types as well as generic meta data. Previously, a mock type did not preserve
+ * annotations on types unless they were explicitly inherited and never retained annotations on methods. As a consequence, the following
+ * conditions now hold true:
+ *
+ * <pre class="code"><code class="java">
+ * {@literal @}{@code MyAnnotation
+ *  class Foo {
+ *    List<String> bar() { ... }
+ *  }
+ *
+ *  Class<?> mockType = mock(Foo.class).getClass();
+ *  assert mockType.isAnnotationPresent(MyAnnotation.class);
+ *  assert mockType.getDeclaredMethod("bar").getGenericReturnType() instanceof ParameterizedType;
+ * }</code></pre>
+ *
+ * <p>
+ * When using Java 8, Mockito now also preserves type annotations. This is default behavior and might not hold <a href="#28">if an
+ * alternative {@link org.mockito.plugins.MockMaker} is used</a>.
+ *
+ * <h3 id="39">39. <a class="meaningful_link" href="#Mocking_Final" name="Mocking_Final">Mocking final types, enums and final methods</a> (Since 2.1.0)</h3>
+ *
+ * Mockito now offers an {@link Incubating}, optional support for mocking final classes and methods.
+ * This is a fantastic improvement that demonstrates Mockito's everlasting quest for improving testing experience.
+ * Our ambition is that Mockito "just works" with final classes and methods.
+ * Previously they were considered <em>unmockable</em>, preventing the user from mocking.
+ * We already started discussing how to make this feature enabled by default.
+ * Currently, the feature is still optional as we wait for more feedback from the community.
+ *
+ * <p>
+ * This feature is turned off by default because it is based on completely different mocking mechanism
+ * that requires more feedback from the community.
+ *
+ * <p>
+ * This alternative mock maker which uses
+ * a combination of both Java instrumentation API and sub-classing rather than creating a new class to represent
+ * a mock. This way, it becomes possible to mock final types and methods.
+ *
+ * <p>
+ * This mock maker is <strong>turned off by default</strong> because it is based on completely different mocking mechanism
+ * that requires more feedback from the community. It can be activated explicitly by the mockito extension mechanism,
+ * just create in the classpath a file <code>/mockito-extensions/org.mockito.plugins.MockMaker</code>
+ * containing the value <code>mock-maker-inline</code>.
+ *
+ * <p>
+ * As a convenience, the Mockito team provides an artifact where this mock maker is preconfigured. Instead of using the
+ * <i>mockito-core</i> artifact, include the <i>mockito-inline</i> artifact in your project. Note that this artifact is
+ * likely to be discontinued once mocking of final classes and methods gets integrated into the default mock maker.
+ *
+ * <p>
+ * Some noteworthy notes about this mock maker:
+ * <ul>
+ *     <li>Mocking final types and enums is incompatible with mock settings like :
+ *     <ul>
+ *         <li>explicitly serialization support <code>withSettings().serializable()</code></li>
+ *         <li>extra-interfaces <code>withSettings().extraInterfaces()</code></li>
+ *     </ul>
+ *     </li>
+ *     <li>Some methods cannot be mocked
+ *         <ul>
+ *              <li>Package-visible methods of <code>java.*</code></li>
+ *              <li><code>native</code> methods</li>
+ *         </ul>
+ *     </li>
+ *     <li>This mock maker has been designed around Java Agent runtime attachment ; this require a compatible JVM,
+ *     that is part of the JDK (or Java 9 VM). When running on a non-JDK VM prior to Java 9, it is however possible to
+ *     manually add the <a href="http://bytebuddy.net">Byte Buddy Java agent jar</a> using the <code>-javaagent</code>
+ *     parameter upon starting the JVM.
+ *     </li>
+ * </ul>
+ *
+ * <p>
+ * If you are interested in more details of this feature please read the javadoc of
+ * <code>org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker</code>
+ *
+ * <h3 id="40">40. <a class="meaningful_link" href="#strict_mockito" name="strict_mockito">
+ *     (**new**) Improved productivity and cleaner tests with "stricter" Mockito</a> (Since 2.+)</h3>
+ *
+ * To quickly find out how "stricter" Mockito can make you more productive and get your tests cleaner, see:
+ * <ul>
+ *     <li>Strict stubbing with JUnit Rules - {@link MockitoRule#strictness(Strictness)} with {@link Strictness#STRICT_STUBS}</li>
+ *     <li>Strict stubbing with JUnit Runner - {@link MockitoJUnitRunner.StrictStubs}</li>
+ *     <li>Strict stubbing if you cannot use runner/rule (like TestNG) - {@link MockitoSession}</li>
+ *     <li>Unnecessary stubbing detection with {@link MockitoJUnitRunner}</li>
+ *     <li>Stubbing argument mismatch warnings, documented in {@link MockitoHint}</li>
+ * </ul>
+ *
+ * Mockito is a "loose" mocking framework by default.
+ * Mocks can be interacted with without setting any expectations beforehand.
+ * This is intentional and it improves the quality of tests by forcing users to be explicit about what they want to stub / verify.
+ * It is also very intuitive, easy to use and blends nicely with "given", "when", "then" template of clean test code.
+ * This is also different from the classic mocking frameworks of the past, they were "strict" by default.
+ * <p>
+ * Being "loose" by default makes Mockito tests harder to debug at times.
+ * There are scenarios where misconfigured stubbing (like using a wrong argument) forces the user to run the test with a debugger.
+ * Ideally, tests failures are immediately obvious and don't require debugger to identify the root cause.
+ * Starting with version 2.1 Mockito has been getting new features that nudge the framework towards "strictness".
+ * We want Mockito to offer fantastic debuggability while not losing its core mocking style, optimized for
+ * intuitiveness, explicitness and clean test code.
+ * <p>
+ * Help Mockito! Try the new features, give us feedback, join the discussion about Mockito strictness at GitHub
+ * <a href="https://github.com/mockito/mockito/issues/769">issue 769</a>.
+ */
+@SuppressWarnings("unchecked")
+public class Mockito extends ArgumentMatchers {
+
+    static final MockitoCore MOCKITO_CORE = new MockitoCore();
+
+    /**
+     * The default <code>Answer</code> of every mock <b>if</b> the mock was not stubbed.
+     *
+     * Typically it just returns some empty value.
+     * <p>
+     * {@link Answer} can be used to define the return values of unstubbed invocations.
+     * <p>
+     * This implementation first tries the global configuration and if there is no global configuration then
+     * it will use a default answer that returns zeros, empty collections, nulls, etc.
+     */
+    public static final Answer<Object> RETURNS_DEFAULTS = Answers.RETURNS_DEFAULTS;
+
+    /**
+     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.
+     * <p>
+     * {@link Answer} can be used to define the return values of unstubbed invocations.
+     * <p>
+     * This implementation can be helpful when working with legacy code.
+     * Unstubbed methods often return null. If your code uses the object returned by an unstubbed call you get a NullPointerException.
+     * This implementation of Answer <b>returns SmartNull instead of null</b>.
+     * <code>SmartNull</code> gives nicer exception message than NPE because it points out the line where unstubbed method was called. You just click on the stack trace.
+     * <p>
+     * <code>ReturnsSmartNulls</code> first tries to return ordinary values (zeros, empty collections, empty string, etc.)
+     * then it tries to return SmartNull. If the return type is final then plain <code>null</code> is returned.
+     * <p>
+     * <code>ReturnsSmartNulls</code> will be probably the default return values strategy in Mockito 3.0.0
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     *   Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+     *
+     *   //calling unstubbed method here:
+     *   Stuff stuff = mock.getStuff();
+     *
+     *   //using object returned by unstubbed call:
+     *   stuff.doSomething();
+     *
+     *   //Above doesn't yield NullPointerException this time!
+     *   //Instead, SmartNullPointerException is thrown.
+     *   //Exception's cause links to unstubbed <i>mock.getStuff()</i> - just click on the stack trace.
+     * </code></pre>
+     */
+    public static final Answer<Object> RETURNS_SMART_NULLS = Answers.RETURNS_SMART_NULLS;
+
+    /**
+     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}
+     * <p>
+     * {@link Answer} can be used to define the return values of unstubbed invocations.
+     * <p>
+     * This implementation can be helpful when working with legacy code.
+     * <p>
+     * ReturnsMocks first tries to return ordinary values (zeros, empty collections, empty string, etc.)
+     * then it tries to return mocks. If the return type cannot be mocked (e.g. is final) then plain <code>null</code> is returned.
+     * <p>
+     */
+    public static final Answer<Object> RETURNS_MOCKS = Answers.RETURNS_MOCKS;
+
+    /**
+     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.
+     * <p>
+     * Example that shows how deep stub works:
+     * <pre class="code"><code class="java">
+     *   Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
+     *
+     *   // note that we're stubbing a chain of methods here: getBar().getName()
+     *   when(mock.getBar().getName()).thenReturn("deep");
+     *
+     *   // note that we're chaining method calls: getBar().getName()
+     *   assertEquals("deep", mock.getBar().getName());
+     * </code></pre>
+     * </p>
+     *
+     * <p>
+     * <strong>WARNING: </strong>
+     * This feature should rarely be required for regular clean code! Leave it for legacy code.
+     * Mocking a mock to return a mock, to return a mock, (...), to return something meaningful
+     * hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).
+     * </p>
+     *
+     * <p>
+     * Good quote I've seen one day on the web: <strong>every time a mock returns a mock a fairy dies</strong>.
+     * </p>
+     *
+     * <p>
+     * Please note that this answer will return existing mocks that matches the stub. This
+     * behavior is ok with deep stubs and allows verification to work on the last mock of the chain.
+     * <pre class="code"><code class="java">
+     *   when(mock.getBar(anyString()).getThingy().getName()).thenReturn("deep");
+     *
+     *   mock.getBar("candy bar").getThingy().getName();
+     *
+     *   assertSame(mock.getBar(anyString()).getThingy().getName(), mock.getBar(anyString()).getThingy().getName());
+     *   verify(mock.getBar("candy bar").getThingy()).getName();
+     *   verify(mock.getBar(anyString()).getThingy()).getName();
+     * </code></pre>
+     * </p>
+     *
+     * <p>
+     * Verification only works with the last mock in the chain. You can use verification modes.
+     * <pre class="code"><code class="java">
+     *   when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
+     *   when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep");
+     *   when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep");
+     *
+     *   person.getAddress("the docks").getStreet().getName();
+     *   person.getAddress("the docks").getStreet().getLongName();
+     *   person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
+     *   person.getAddress("the docks").getStreet(Locale.CHINESE).getName();
+     *
+     *   // note that we are actually referring to the very last mock in the stubbing chain.
+     *   InOrder inOrder = inOrder(
+     *       person.getAddress("the docks").getStreet(),
+     *       person.getAddress("the docks").getStreet(Locale.CHINESE),
+     *       person.getAddress("the docks").getStreet(Locale.ITALIAN)
+     *   );
+     *   inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();
+     *   inOrder.verify(person.getAddress("the docks").getStreet()).getLongName();
+     *   inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1)).getName();
+     *   inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();
+     * </code></pre>
+     * </p>
+     *
+     * <p>
+     * How deep stub work internally?
+     * <pre class="code"><code class="java">
+     *   //this:
+     *   Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
+     *   when(mock.getBar().getName(), "deep");
+     *
+     *   //is equivalent of
+     *   Foo foo = mock(Foo.class);
+     *   Bar bar = mock(Bar.class);
+     *   when(foo.getBar()).thenReturn(bar);
+     *   when(bar.getName()).thenReturn("deep");
+     * </code></pre>
+     * </p>
+     *
+     * <p>
+     * This feature will not work when any return type of methods included in the chain cannot be mocked
+     * (for example: is a primitive or a final class). This is because of java type system.
+     * </p>
+     */
+    public static final Answer<Object> RETURNS_DEEP_STUBS = Answers.RETURNS_DEEP_STUBS;
+
+    /**
+     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}
+     * <p>
+     * {@link Answer} can be used to define the return values of unstubbed invocations.
+     * <p>
+     * This implementation can be helpful when working with legacy code.
+     * When this implementation is used, unstubbed methods will delegate to the real implementation.
+     * This is a way to create a partial mock object that calls real methods by default.
+     * <p>
+     * As usual you are going to read <b>the partial mock warning</b>:
+     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+     * How does partial mock fit into this paradigm? Well, it just doesn't...
+     * Partial mock usually means that the complexity has been moved to a different method on the same object.
+     * In most cases, this is not the way you want to design your application.
+     * <p>
+     * However, there are rare cases when partial mocks come handy:
+     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     * Foo mock = mock(Foo.class, CALLS_REAL_METHODS);
+     *
+     * // this calls the real implementation of Foo.getSomething()
+     * value = mock.getSomething();
+     *
+     * when(mock.getSomething()).thenReturn(fakeValue);
+     *
+     * // now fakeValue is returned
+     * value = mock.getSomething();
+     * </code></pre>
+     */
+    public static final Answer<Object> CALLS_REAL_METHODS = Answers.CALLS_REAL_METHODS;
+
+    /**
+     * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.
+     *
+     * Allows Builder mocks to return itself whenever a method is invoked that returns a Type equal
+     * to the class or a superclass.
+     *
+     * <p><b>Keep in mind this answer uses the return type of a method.
+     * If this type is assignable to the class of the mock, it will return the mock.
+     * Therefore if you have a method returning a superclass (for example {@code Object}) it will match and return the mock.</b></p>
+     *
+     * Consider a HttpBuilder used in a HttpRequesterWithHeaders.
+     *
+     * <pre class="code"><code class="java">
+     * public class HttpRequesterWithHeaders {
+     *
+     *      private HttpBuilder builder;
+     *
+     *      public HttpRequesterWithHeaders(HttpBuilder builder) {
+     *          this.builder = builder;
+     *      }
+     *
+     *      public String request(String uri) {
+     *          return builder.withUrl(uri)
+     *                  .withHeader("Content-type: application/json")
+     *                  .withHeader("Authorization: Bearer")
+     *                  .request();
+     *      }
+     *  }
+     *
+     *  private static class HttpBuilder {
+     *
+     *      private String uri;
+     *      private List&lt;String&gt; headers;
+     *
+     *      public HttpBuilder() {
+     *          this.headers = new ArrayList&lt;String&gt;();
+     *      }
+     *
+     *       public HttpBuilder withUrl(String uri) {
+     *           this.uri = uri;
+     *           return this;
+     *       }
+     *
+     *       public HttpBuilder withHeader(String header) {
+     *           this.headers.add(header);
+     *           return this;
+     *       }
+     *
+     *       public String request() {
+     *          return uri + headers.toString();
+     *       }
+     *  }
+     * </code></pre>
+     *
+     * The following test will succeed
+     *
+     * <pre><code>
+     * &#064;Test
+     *  public void use_full_builder_with_terminating_method() {
+     *      HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF);
+     *      HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder);
+     *      String response = "StatusCode: 200";
+     *
+     *      when(builder.request()).thenReturn(response);
+     *
+     *      assertThat(requester.request("URI")).isEqualTo(response);
+     *  }
+     * </code></pre>
+     */
+    public static final Answer<Object> RETURNS_SELF = Answers.RETURNS_SELF;
+
+    /**
+     * Creates mock object of given class or interface.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param classToMock class or interface to mock
+     * @return mock object
+     */
+    public static <T> T mock(Class<T> classToMock) {
+        return mock(classToMock, withSettings());
+    }
+
+    /**
+     * Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
+     * <p>
+     * Beware that naming mocks is not a solution for complex code which uses too many mocks or collaborators.
+     * <b>If you have too many mocks then refactor the code</b> so that it's easy to test/debug without necessity of naming mocks.
+     * <p>
+     * <b>If you use <code>&#064;Mock</code> annotation then you've got naming mocks for free!</b> <code>&#064;Mock</code> uses field name as mock name. {@link Mock Read more.}
+     * <p>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param classToMock class or interface to mock
+     * @param name of the mock
+     * @return mock object
+     */
+    public static <T> T mock(Class<T> classToMock, String name) {
+        return mock(classToMock, withSettings()
+                .name(name)
+                .defaultAnswer(RETURNS_DEFAULTS));
+    }
+
+    /**
+     * Returns a MockingDetails instance that enables inspecting a particular object for Mockito related information.
+     * Can be used to find out if given object is a Mockito mock
+     * or to find out if a given mock is a spy or mock.
+     * <p>
+     * In future Mockito versions MockingDetails may grow and provide other useful information about the mock,
+     * e.g. invocations, stubbing info, etc.
+     *
+     * @param toInspect - object to inspect. null input is allowed.
+     * @return A {@link org.mockito.MockingDetails} instance.
+     * @since 1.9.5
+     */
+    public static MockingDetails mockingDetails(Object toInspect) {
+        return MOCKITO_CORE.mockingDetails(toInspect);
+    }
+
+    /**
+     * Creates mock with a specified strategy for its answers to interactions.
+     * It's quite an advanced feature and typically you don't need it to write decent tests.
+     * However it can be helpful when working with legacy systems.
+     * <p>
+     * It is the default answer so it will be used <b>only when you don't</b> stub the method call.
+     *
+     * <pre class="code"><code class="java">
+     *   Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+     *   Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+     * </code></pre>
+     *
+     * <p>See examples in javadoc for {@link Mockito} class</p>
+     *
+     * @param classToMock class or interface to mock
+     * @param defaultAnswer default answer for unstubbed methods
+     *
+     * @return mock object
+     */
+    public static <T> T mock(Class<T> classToMock, Answer defaultAnswer) {
+        return mock(classToMock, withSettings().defaultAnswer(defaultAnswer));
+    }
+
+    /**
+     * Creates a mock with some non-standard settings.
+     * <p>
+     * The number of configuration points for a mock grows
+     * so we need a fluent way to introduce new configuration without adding more and more overloaded Mockito.mock() methods.
+     * Hence {@link MockSettings}.
+     * <pre class="code"><code class="java">
+     *   Listener mock = mock(Listener.class, withSettings()
+     *     .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
+     *   );
+     * </code></pre>
+     * <b>Use it carefully and occasionally</b>. What might be reason your test needs non-standard mocks?
+     * Is the code under test so complicated that it requires non-standard mocks?
+     * Wouldn't you prefer to refactor the code under test so it is testable in a simple way?
+     * <p>
+     * See also {@link Mockito#withSettings()}
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param classToMock class or interface to mock
+     * @param mockSettings additional mock settings
+     * @return mock object
+     */
+    public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
+        return MOCKITO_CORE.mock(classToMock, mockSettings);
+    }
+
+    /**
+     * Creates a spy of the real object. The spy calls <b>real</b> methods unless they are stubbed.
+     * <p>
+     * Real spies should be used <b>carefully and occasionally</b>, for example when dealing with legacy code.
+     * <p>
+     * As usual you are going to read <b>the partial mock warning</b>:
+     * Object oriented programming tackles complexity by dividing the complexity into separate, specific, SRPy objects.
+     * How does partial mock fit into this paradigm? Well, it just doesn't...
+     * Partial mock usually means that the complexity has been moved to a different method on the same object.
+     * In most cases, this is not the way you want to design your application.
+     * <p>
+     * However, there are rare cases when partial mocks come handy:
+     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+     * <p>
+     * Example:
+     *
+     * <pre class="code"><code class="java">
+     *   List list = new LinkedList();
+     *   List spy = spy(list);
+     *
+     *   //optionally, you can stub out some methods:
+     *   when(spy.size()).thenReturn(100);
+     *
+     *   //using the spy calls <b>real</b> methods
+     *   spy.add("one");
+     *   spy.add("two");
+     *
+     *   //prints "one" - the first element of a list
+     *   System.out.println(spy.get(0));
+     *
+     *   //size() method was stubbed - 100 is printed
+     *   System.out.println(spy.size());
+     *
+     *   //optionally, you can verify
+     *   verify(spy).add("one");
+     *   verify(spy).add("two");
+     * </code></pre>
+     *
+     * <h4>Important gotcha on spying real objects!</h4>
+     * <ol>
+     * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.
+     * Therefore for spies it is recommended to always use <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code>|<code>CallRealMethod</code>
+     * family of methods for stubbing. Example:
+     *
+     * <pre class="code"><code class="java">
+     *   List list = new LinkedList();
+     *   List spy = spy(list);
+     *
+     *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+     *   when(spy.get(0)).thenReturn("foo");
+     *
+     *   //You have to use doReturn() for stubbing
+     *   doReturn("foo").when(spy).get(0);
+     * </code></pre>
+     * </li>
+     *
+     * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.
+     * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction
+     * and their effect on real instance state.
+     * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,
+     * you won't see any effects on the real instance.</li>
+     *
+     * <li>Watch out for final methods.
+     * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.
+     * Also you won't be able to verify those method as well.
+     * </li>
+     * </ol>
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * <p>Note that the spy won't have any annotations of the spied type, because CGLIB won't rewrite them.
+     * It may troublesome for code that rely on the spy to have these annotations.</p>
+     *
+     *
+     * @param object
+     *            to spy on
+     * @return a spy of the real object
+     */
+    public static <T> T spy(T object) {
+        return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
+                .spiedInstance(object)
+                .defaultAnswer(CALLS_REAL_METHODS));
+    }
+
+    /**
+     * Please refer to the documentation of {@link #spy(Object)}.
+     * Overusing spies hints at code design smells.
+     * <p>
+     * This method, in contrast to the original {@link #spy(Object)}, creates a spy based on class instead of an object.
+     * Sometimes it is more convenient to create spy based on the class and avoid providing an instance of a spied object.
+     * This is particularly useful for spying on abstract classes because they cannot be instantiated.
+     * See also {@link MockSettings#useConstructor()}.
+     * <p>
+     * Examples:
+     * <pre class="code"><code class="java">
+     *   SomeAbstract spy = spy(SomeAbstract.class);
+     *
+     *   //Robust API, via settings builder:
+     *   OtherAbstract spy = mock(OtherAbstract.class, withSettings()
+     *      .useConstructor().defaultAnswer(CALLS_REAL_METHODS));
+     *
+     *   //Mocking a non-static inner abstract class:
+     *   InnerAbstract spy = mock(InnerAbstract.class, withSettings()
+     *      .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));
+     * </code></pre>
+     *
+     * @param classToSpy the class to spy
+     * @param <T> type of the spy
+     * @return a spy of the provided class
+     * @since 1.10.12
+     */
+    @Incubating
+    public static <T> T spy(Class<T> classToSpy) {
+        return MOCKITO_CORE.mock(classToSpy, withSettings()
+                .useConstructor()
+                .defaultAnswer(CALLS_REAL_METHODS));
+    }
+
+    /**
+     * Enables stubbing methods. Use it when you want the mock to return particular value when particular method is called.
+     * <p>
+     * Simply put: "<b>When</b> the x method is called <b>then</b> return y".
+     *
+     * <p>
+     * Examples:
+     *
+     * <pre class="code"><code class="java">
+     * <b>when</b>(mock.someMethod()).<b>thenReturn</b>(10);
+     *
+     * //you can use flexible argument matchers, e.g:
+     * when(mock.someMethod(<b>anyString()</b>)).thenReturn(10);
+     *
+     * //setting exception to be thrown:
+     * when(mock.someMethod("some arg")).thenThrow(new RuntimeException());
+     *
+     * //you can set different behavior for consecutive method calls.
+     * //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.
+     * when(mock.someMethod("some arg"))
+     *  .thenThrow(new RuntimeException())
+     *  .thenReturn("foo");
+     *
+     * //Alternative, shorter version for consecutive stubbing:
+     * when(mock.someMethod("some arg"))
+     *  .thenReturn("one", "two");
+     * //is the same as:
+     * when(mock.someMethod("some arg"))
+     *  .thenReturn("one")
+     *  .thenReturn("two");
+     *
+     * //shorter version for consecutive method calls throwing exceptions:
+     * when(mock.someMethod("some arg"))
+     *  .thenThrow(new RuntimeException(), new NullPointerException();
+     *
+     * </code></pre>
+     *
+     * For stubbing void methods with throwables see: {@link Mockito#doThrow(Throwable...)}
+     * <p>
+     * Stubbing can be overridden: for example common stubbing can go to fixture
+     * setup but the test methods can override it.
+     * Please note that overridding stubbing is a potential code smell that points out too much stubbing.
+     * <p>
+     * Once stubbed, the method will always return stubbed value regardless
+     * of how many times it is called.
+     * <p>
+     * Last stubbing is more important - when you stubbed the same method with
+     * the same arguments many times.
+     * <p>
+     * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.
+     * Let's say you've stubbed <code>foo.bar()</code>.
+     * If your code cares what <code>foo.bar()</code> returns then something else breaks(often before even <code>verify()</code> gets executed).
+     * If your code doesn't care what <code>get(0)</code> returns then it should not be stubbed.
+     * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+     *
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     * @param methodCall method to be stubbed
+     * @return OngoingStubbing object used to stub fluently.
+     *         <strong>Do not</strong> create a reference to this returned object.
+     */
+    public static <T> OngoingStubbing<T> when(T methodCall) {
+        return MOCKITO_CORE.when(methodCall);
+    }
+
+    /**
+     * Verifies certain behavior <b>happened once</b>.
+     * <p>
+     * Alias to <code>verify(mock, times(1))</code> E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock).someMethod("some arg");
+     * </code></pre>
+     * Above is equivalent to:
+     * <pre class="code"><code class="java">
+     *   verify(mock, times(1)).someMethod("some arg");
+     * </code></pre>
+     * <p>
+     * Arguments passed are compared using <code>equals()</code> method.
+     * Read about {@link ArgumentCaptor} or {@link ArgumentMatcher} to find out other ways of matching / asserting arguments passed.
+     * <p>
+     * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.
+     * Let's say you've stubbed <code>foo.bar()</code>.
+     * If your code cares what <code>foo.bar()</code> returns then something else breaks(often before even <code>verify()</code> gets executed).
+     * If your code doesn't care what <code>get(0)</code> returns then it should not be stubbed.
+     * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+     *
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param mock to be verified
+     * @return mock object itself
+     */
+    public static <T> T verify(T mock) {
+        return MOCKITO_CORE.verify(mock, times(1));
+    }
+
+    /**
+     * Verifies certain behavior happened at least once / exact number of times / never. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, times(5)).someMethod("was called five times");
+     *
+     *   verify(mock, atLeast(2)).someMethod("was called at least two times");
+     *
+     *   //you can use flexible argument matchers, e.g:
+     *   verify(mock, atLeastOnce()).someMethod(<b>anyString()</b>);
+     * </code></pre>
+     *
+     * <b>times(1) is the default</b> and can be omitted
+     * <p>
+     * Arguments passed are compared using <code>equals()</code> method.
+     * Read about {@link ArgumentCaptor} or {@link ArgumentMatcher} to find out other ways of matching / asserting arguments passed.
+     * <p>
+     *
+     * @param mock to be verified
+     * @param mode times(x), atLeastOnce() or never()
+     *
+     * @return mock object itself
+     */
+    public static <T> T verify(T mock, VerificationMode mode) {
+        return MOCKITO_CORE.verify(mock, mode);
+    }
+
+    /**
+     * Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.
+     * Normally, you don't need to reset your mocks, just create new mocks for each test method.
+     * <p>
+     * Instead of <code>#reset()</code> please consider writing simple, small and focused test methods over lengthy, over-specified tests.
+     * <b>First potential code smell is <code>reset()</code> in the middle of the test method.</b> This probably means you're testing too much.
+     * Follow the whisper of your test methods: "Please keep us small & focused on single behavior".
+     * There are several threads about it on mockito mailing list.
+     * <p>
+     * The only reason we added <code>reset()</code> method is to
+     * make it possible to work with container-injected mocks.
+     * For more information see the FAQ (<a href="https://github.com/mockito/mockito/wiki/FAQ">here</a>).
+     * <p>
+     * <b>Don't harm yourself.</b> <code>reset()</code> in the middle of the test method is a code smell (you're probably testing too much).
+     * <pre class="code"><code class="java">
+     *   List mock = mock(List.class);
+     *   when(mock.size()).thenReturn(10);
+     *   mock.add(1);
+     *
+     *   reset(mock);
+     *   //at this point the mock forgot any interactions & stubbing
+     * </code></pre>
+     *
+     * @param <T> The Type of the mocks
+     * @param mocks to be reset
+     */
+    public static <T> void reset(T ... mocks) {
+        MOCKITO_CORE.reset(mocks);
+    }
+
+    /**
+     * Use this method in order to only clear invocations, when stubbing is non-trivial. Use-cases can be:
+     * <ul>
+     *     <li>You are using a dependency injection framework to inject your mocks.</li>
+     *     <li>The mock is used in a stateful scenario. For example a class is Singleton which depends on your mock.</li>
+     * </ul>
+     *
+     * <b>Try to avoid this method at all costs. Only clear invocations if you are unable to efficiently test your program.</b>
+     * @param <T> The type of the mocks
+     * @param mocks The mocks to clear the invocations for
+     */
+    public static <T> void clearInvocations(T ... mocks) {
+        MOCKITO_CORE.clearInvocations(mocks);
+    }
+
+    /**
+     * Checks if any of given mocks has any unverified interaction.
+     * <p>
+     * You can use this method after you verified your mocks - to make sure that nothing
+     * else was invoked on your mocks.
+     * <p>
+     * See also {@link Mockito#never()} - it is more explicit and communicates the intent well.
+     * <p>
+     * Stubbed invocations (if called) are also treated as interactions.
+     * <p>
+     * A word of <b>warning</b>:
+     * Some users who did a lot of classic, expect-run-verify mocking tend to use <code>verifyNoMoreInteractions()</code> very often, even in every test method.
+     * <code>verifyNoMoreInteractions()</code> is not recommended to use in every test method.
+     * <code>verifyNoMoreInteractions()</code> is a handy assertion from the interaction testing toolkit. Use it only when it's relevant.
+     * Abusing it leads to overspecified, less maintainable tests. You can find further reading
+     * <a href="http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/">here</a>.
+     * <p>
+     * This method will also detect unverified invocations that occurred before the test method,
+     * for example: in <code>setUp()</code>, <code>&#064;Before</code> method or in constructor.
+     * Consider writing nice code that makes interactions only in test methods.
+     *
+     * <p>
+     * Example:
+     *
+     * <pre class="code"><code class="java">
+     * //interactions
+     * mock.doSomething();
+     * mock.doSomethingUnexpected();
+     *
+     * //verification
+     * verify(mock).doSomething();
+     *
+     * //following will fail because 'doSomethingUnexpected()' is unexpected
+     * verifyNoMoreInteractions(mock);
+     *
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param mocks to be verified
+     */
+    public static void verifyNoMoreInteractions(Object... mocks) {
+        MOCKITO_CORE.verifyNoMoreInteractions(mocks);
+    }
+
+    /**
+     * Verifies that no interactions happened on given mocks.
+     * <pre class="code"><code class="java">
+     *   verifyZeroInteractions(mockOne, mockTwo);
+     * </code></pre>
+     * This method will also detect invocations
+     * that occurred before the test method, for example: in <code>setUp()</code>, <code>&#064;Before</code> method or in constructor.
+     * Consider writing nice code that makes interactions only in test methods.
+     * <p>
+     * See also {@link Mockito#never()} - it is more explicit and communicates the intent well.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param mocks to be verified
+     */
+    public static void verifyZeroInteractions(Object... mocks) {
+        MOCKITO_CORE.verifyNoMoreInteractions(mocks);
+    }
+
+    /**
+     * Use <code>doThrow()</code> when you want to stub the void method with an exception.
+     * <p>
+     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler
+     * does not like void methods inside brackets...
+     * <p>
+     * Example:
+     *
+     * <pre class="code"><code class="java">
+     *   doThrow(new RuntimeException()).when(mock).someVoidMethod();
+     * </code></pre>
+     *
+     * @param toBeThrown to be thrown when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    public static Stubber doThrow(Throwable... toBeThrown) {
+        return MOCKITO_CORE.stubber().doThrow(toBeThrown);
+    }
+
+    /**
+     * Use <code>doThrow()</code> when you want to stub the void method with an exception.
+     * <p>
+     * A new exception instance will be created for each method invocation.
+     * <p>
+     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler
+     * does not like void methods inside brackets...
+     * <p>
+     * Example:
+     *
+     * <pre class="code"><code class="java">
+     *   doThrow(RuntimeException.class).when(mock).someVoidMethod();
+     * </code></pre>
+     *
+     * @param toBeThrown to be thrown when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     * @since 2.1.0
+     */
+    public static Stubber doThrow(Class<? extends Throwable> toBeThrown) {
+        return MOCKITO_CORE.stubber().doThrow(toBeThrown);
+    }
+
+    /**
+     * Same as {@link #doThrow(Class)} but sets consecutive exception classes to be thrown. Remember to use
+     * <code>doThrow()</code> when you want to stub the void method to throw several exception of specified class.
+     * <p>
+     * A new exception instance will be created for each method invocation.
+     * <p>
+     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler
+     * does not like void methods inside brackets...
+     * <p>
+     * Example:
+     *
+     * <pre class="code"><code class="java">
+     *   doThrow(RuntimeException.class, BigFailure.class).when(mock).someVoidMethod();
+     * </code></pre>
+     *
+     * @param toBeThrown to be thrown when the stubbed method is called
+     * @param toBeThrownNext next to be thrown when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     * @since 2.1.0
+     */
+    // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation
+    @SuppressWarnings ({"unchecked", "varargs"})
+    public static Stubber doThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... toBeThrownNext) {
+        return MOCKITO_CORE.stubber().doThrow(toBeThrown, toBeThrownNext);
+    }
+
+
+    /**
+     * Use <code>doCallRealMethod()</code> when you want to call the real implementation of a method.
+     * <p>
+     * As usual you are going to read <b>the partial mock warning</b>:
+     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+     * How does partial mock fit into this paradigm? Well, it just doesn't...
+     * Partial mock usually means that the complexity has been moved to a different method on the same object.
+     * In most cases, this is not the way you want to design your application.
+     * <p>
+     * However, there are rare cases when partial mocks come handy:
+     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+     * <p>
+     * See also javadoc {@link Mockito#spy(Object)} to find out more about partial mocks.
+     * <b>Mockito.spy() is a recommended way of creating partial mocks.</b>
+     * The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     *   Foo mock = mock(Foo.class);
+     *   doCallRealMethod().when(mock).someVoidMethod();
+     *
+     *   // this will call the real implementation of Foo.someVoidMethod()
+     *   mock.someVoidMethod();
+     * </code></pre>
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @return stubber - to select a method for stubbing
+     * @since 1.9.5
+     */
+    public static Stubber doCallRealMethod() {
+        return MOCKITO_CORE.stubber().doCallRealMethod();
+    }
+
+    /**
+     * Use <code>doAnswer()</code> when you want to stub a void method with generic {@link Answer}.
+     * <p>
+     * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...
+     * <p>
+     * Example:
+     *
+     * <pre class="code"><code class="java">
+     *  doAnswer(new Answer() {
+     *      public Object answer(InvocationOnMock invocation) {
+     *          Object[] args = invocation.getArguments();
+     *          Mock mock = invocation.getMock();
+     *          return null;
+     *      }})
+     *  .when(mock).someMethod();
+     * </code></pre>
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param answer to answer when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    public static Stubber doAnswer(Answer answer) {
+        return MOCKITO_CORE.stubber().doAnswer(answer);
+    }
+
+    /**
+     * Use <code>doNothing()</code> for setting void methods to do nothing. <b>Beware that void methods on mocks do nothing by default!</b>
+     * However, there are rare situations when doNothing() comes handy:
+     * <p>
+     * <ol>
+     * <li>Stubbing consecutive calls on a void method:
+     * <pre class="code"><code class="java">
+     *   doNothing().
+     *   doThrow(new RuntimeException())
+     *   .when(mock).someVoidMethod();
+     *
+     *   //does nothing the first time:
+     *   mock.someVoidMethod();
+     *
+     *   //throws RuntimeException the next time:
+     *   mock.someVoidMethod();
+     * </code></pre>
+     * </li>
+     * <li>When you spy real objects and you want the void method to do nothing:
+     * <pre class="code"><code class="java">
+     *   List list = new LinkedList();
+     *   List spy = spy(list);
+     *
+     *   //let's make clear() do nothing
+     *   doNothing().when(spy).clear();
+     *
+     *   spy.add("one");
+     *
+     *   //clear() does nothing, so the list still contains "one"
+     *   spy.clear();
+     * </code></pre>
+     * </li>
+     * </ol>
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @return stubber - to select a method for stubbing
+     */
+    public static Stubber doNothing() {
+        return MOCKITO_CORE.stubber().doNothing();
+    }
+
+    /**
+     * Use <code>doReturn()</code> in those rare occasions when you cannot use {@link Mockito#when(Object)}.
+     * <p>
+     * <b>Beware that {@link Mockito#when(Object)} is always recommended for stubbing because it is argument type-safe
+     * and more readable</b> (especially when stubbing consecutive calls).
+     * <p>
+     * Here are those rare occasions when doReturn() comes handy:
+     * <p>
+     *
+     * <ol>
+     * <li>When spying real objects and calling real methods on a spy brings side effects
+     *
+     * <pre class="code"><code class="java">
+     *   List list = new LinkedList();
+     *   List spy = spy(list);
+     *
+     *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+     *   when(spy.get(0)).thenReturn("foo");
+     *
+     *   //You have to use doReturn() for stubbing:
+     *   doReturn("foo").when(spy).get(0);
+     * </code></pre>
+     * </li>
+     *
+     * <li>Overriding a previous exception-stubbing:
+     * <pre class="code"><code class="java">
+     *   when(mock.foo()).thenThrow(new RuntimeException());
+     *
+     *   //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
+     *   when(mock.foo()).thenReturn("bar");
+     *
+     *   //You have to use doReturn() for stubbing:
+     *   doReturn("bar").when(mock).foo();
+     * </code></pre>
+     * </li>
+     * </ol>
+     *
+     * Above scenarios shows a tradeoff of Mockito's elegant syntax. Note that the scenarios are very rare, though.
+     * Spying should be sporadic and overriding exception-stubbing is very rare. Not to mention that in general
+     * overridding stubbing is a potential code smell that points out too much stubbing.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param toBeReturned to be returned when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    public static Stubber doReturn(Object toBeReturned) {
+        return MOCKITO_CORE.stubber().doReturn(toBeReturned);
+    }
+
+    /**
+     * Same as {@link #doReturn(Object)} but sets consecutive values to be returned. Remember to use
+     * <code>doReturn()</code> in those rare occasions when you cannot use {@link Mockito#when(Object)}.
+     * <p>
+     * <b>Beware that {@link Mockito#when(Object)} is always recommended for stubbing because it is argument type-safe
+     * and more readable</b> (especially when stubbing consecutive calls).
+     * <p>
+     * Here are those rare occasions when doReturn() comes handy:
+     * <p>
+     *
+     * <ol>
+     * <li>When spying real objects and calling real methods on a spy brings side effects
+     *
+     * <pre class="code"><code class="java">
+     *   List list = new LinkedList();
+     *   List spy = spy(list);
+     *
+     *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+     *   when(spy.get(0)).thenReturn("foo", "bar", "qix");
+     *
+     *   //You have to use doReturn() for stubbing:
+     *   doReturn("foo", "bar", "qix").when(spy).get(0);
+     * </code></pre>
+     * </li>
+     *
+     * <li>Overriding a previous exception-stubbing:
+     * <pre class="code"><code class="java">
+     *   when(mock.foo()).thenThrow(new RuntimeException());
+     *
+     *   //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
+     *   when(mock.foo()).thenReturn("bar", "foo", "qix");
+     *
+     *   //You have to use doReturn() for stubbing:
+     *   doReturn("bar", "foo", "qix").when(mock).foo();
+     * </code></pre>
+     * </li>
+     * </ol>
+     *
+     * Above scenarios shows a trade-off of Mockito's elegant syntax. Note that the scenarios are very rare, though.
+     * Spying should be sporadic and overriding exception-stubbing is very rare. Not to mention that in general
+     * overridding stubbing is a potential code smell that points out too much stubbing.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param toBeReturned to be returned when the stubbed method is called
+     * @param toBeReturnedNext to be returned in consecutive calls when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     * @since 2.1.0
+     */
+    @SuppressWarnings({"unchecked", "varargs"})
+    public static Stubber doReturn(Object toBeReturned, Object... toBeReturnedNext) {
+        return MOCKITO_CORE.stubber().doReturn(toBeReturned, toBeReturnedNext);
+    }
+
+    /**
+     * Creates {@link org.mockito.InOrder} object that allows verifying mocks in order.
+     *
+     * <pre class="code"><code class="java">
+     *   InOrder inOrder = inOrder(firstMock, secondMock);
+     *
+     *   inOrder.verify(firstMock).add("was called first");
+     *   inOrder.verify(secondMock).add("was called second");
+     * </code></pre>
+     *
+     * Verification in order is flexible - <b>you don't have to verify all interactions</b> one-by-one
+     * but only those that you are interested in testing in order.
+     * <p>
+     * Also, you can create InOrder object passing only mocks that are relevant for in-order verification.
+     * <p>
+     * <code>InOrder</code> verification is 'greedy', but you will hardly ever notice it.
+     * If you want to find out more, read
+     * <a href="https://github.com/mockito/mockito/wiki/Greedy-algorithm-of-verfication-InOrder">this wiki page</a>.
+     * <p>
+     * As of Mockito 1.8.4 you can verifyNoMoreInvocations() in order-sensitive way. Read more: {@link InOrder#verifyNoMoreInteractions()}
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param mocks to be verified in order
+     *
+     * @return InOrder object to be used to verify in order
+     */
+    public static InOrder inOrder(Object... mocks) {
+        return MOCKITO_CORE.inOrder(mocks);
+    }
+
+    /**
+     * Ignores stubbed methods of given mocks for the sake of verification.
+     * Sometimes useful when coupled with <code>verifyNoMoreInteractions()</code> or verification <code>inOrder()</code>.
+     * Helps avoiding redundant verification of stubbed calls - typically we're not interested in verifying stubs.
+     * <p>
+     * <b>Warning</b>, <code>ignoreStubs()</code> might lead to overuse of <code>verifyNoMoreInteractions(ignoreStubs(...));</code>
+     * Bear in mind that Mockito does not recommend bombarding every test with <code>verifyNoMoreInteractions()</code>
+     * for the reasons outlined in javadoc for {@link Mockito#verifyNoMoreInteractions(Object...)}
+     * Other words: all <b>*stubbed*</b> methods of given mocks are marked <b>*verified*</b> so that they don't get in a way during verifyNoMoreInteractions().
+     * <p>
+     * This method <b>changes the input mocks</b>! This method returns input mocks just for convenience.
+     * <p>
+     * Ignored stubs will also be ignored for verification inOrder, including {@link org.mockito.InOrder#verifyNoMoreInteractions()}.
+     * See the second example.
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     *  //mocking lists for the sake of the example (if you mock List in real you will burn in hell)
+     *  List mock1 = mock(List.class), mock2 = mock(List.class);
+     *
+     *  //stubbing mocks:
+     *  when(mock1.get(0)).thenReturn(10);
+     *  when(mock2.get(0)).thenReturn(20);
+     *
+     *  //using mocks by calling stubbed get(0) methods:
+     *  System.out.println(mock1.get(0)); //prints 10
+     *  System.out.println(mock2.get(0)); //prints 20
+     *
+     *  //using mocks by calling clear() methods:
+     *  mock1.clear();
+     *  mock2.clear();
+     *
+     *  //verification:
+     *  verify(mock1).clear();
+     *  verify(mock2).clear();
+     *
+     *  //verifyNoMoreInteractions() fails because get() methods were not accounted for.
+     *  try { verifyNoMoreInteractions(mock1, mock2); } catch (NoInteractionsWanted e);
+     *
+     *  //However, if we ignore stubbed methods then we can verifyNoMoreInteractions()
+     *  verifyNoMoreInteractions(ignoreStubs(mock1, mock2));
+     *
+     *  //Remember that ignoreStubs() <b>*changes*</b> the input mocks and returns them for convenience.
+     * </code></pre>
+     * Ignoring stubs can be used with <b>verification in order</b>:
+     * <pre class="code"><code class="java">
+     *  List list = mock(List.class);
+     *  when(mock.get(0)).thenReturn("foo");
+     *
+     *  list.add(0);
+     *  System.out.println(list.get(0)); //we don't want to verify this
+     *  list.clear();
+     *
+     *  InOrder inOrder = inOrder(ignoreStubs(list));
+     *  inOrder.verify(list).add(0);
+     *  inOrder.verify(list).clear();
+     *  inOrder.verifyNoMoreInteractions();
+     * </code></pre>
+     *
+     * @since 1.9.0
+     * @param mocks input mocks that will be changed
+     * @return the same mocks that were passed in as parameters
+     */
+    public static Object[] ignoreStubs(Object... mocks) {
+        return MOCKITO_CORE.ignoreStubs(mocks);
+    }
+
+    /**
+     * Allows verifying exact number of invocations. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, times(2)).someMethod("some arg");
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param wantedNumberOfInvocations wanted number of invocations
+     *
+     * @return verification mode
+     */
+    public static VerificationMode times(int wantedNumberOfInvocations) {
+        return VerificationModeFactory.times(wantedNumberOfInvocations);
+    }
+
+    /**
+     * Alias to <code>times(0)</code>, see {@link Mockito#times(int)}
+     * <p>
+     * Verifies that interaction did not happen. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, never()).someMethod();
+     * </code></pre>
+     *
+     * <p>
+     * If you want to verify there were NO interactions with the mock
+     * check out {@link Mockito#verifyZeroInteractions(Object...)}
+     * or {@link Mockito#verifyNoMoreInteractions(Object...)}
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @return verification mode
+     */
+    public static VerificationMode never() {
+        return times(0);
+    }
+
+    /**
+     * Allows at-least-once verification. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, atLeastOnce()).someMethod("some arg");
+     * </code></pre>
+     * Alias to <code>atLeast(1)</code>.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @return verification mode
+     */
+    public static VerificationMode atLeastOnce() {
+        return VerificationModeFactory.atLeastOnce();
+    }
+
+    /**
+     * Allows at-least-x verification. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, atLeast(3)).someMethod("some arg");
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param minNumberOfInvocations minimum number of invocations
+     *
+     * @return verification mode
+     */
+    public static VerificationMode atLeast(int minNumberOfInvocations) {
+        return VerificationModeFactory.atLeast(minNumberOfInvocations);
+    }
+
+    /**
+     * Allows at-most-x verification. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, atMost(3)).someMethod("some arg");
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param maxNumberOfInvocations max number of invocations
+     *
+     * @return verification mode
+     */
+    public static VerificationMode atMost(int maxNumberOfInvocations) {
+        return VerificationModeFactory.atMost(maxNumberOfInvocations);
+    }
+
+    /**
+     * Allows non-greedy verification in order.  For example
+     * <pre class="code"><code class="java">
+     *   inOrder.verify( mock, calls( 2 )).someMethod( "some arg" );
+     * </code></pre>
+     * <ul>
+     * <li>will not fail if the method is called 3 times, unlike times( 2 )</li>
+     * <li>will not mark the third invocation as verified, unlike atLeast( 2 )</li>
+     * </ul>
+     * This verification mode can only be used with in order verification.
+     * @param wantedNumberOfInvocations number of invocations to verify
+     * @return  verification mode
+     */
+    public static VerificationMode calls( int wantedNumberOfInvocations ){
+        return VerificationModeFactory.calls( wantedNumberOfInvocations );
+    }
+
+    /**
+     * Allows checking if given method was the only one invoked. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, only()).someMethod();
+     *   //above is a shorthand for following 2 lines of code:
+     *   verify(mock).someMethod();
+     *   verifyNoMoreInvocations(mock);
+     * </code></pre>
+     *
+     * <p>
+     * See also {@link Mockito#verifyNoMoreInteractions(Object...)}
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @return verification mode
+     */
+    public static VerificationMode only() {
+        return VerificationModeFactory.only();
+    }
+
+    /**
+     * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired
+     * interaction rather than fails immediately if has not already happened. May be useful for testing in concurrent
+     * conditions.
+     * <p>
+     * This differs from {@link Mockito#after after()} in that after() will wait the full period, unless
+     * the final test result is known early (e.g. if a never() fails), whereas timeout() will stop early as soon
+     * as verification passes, producing different behaviour when used with times(2), for example, which can pass
+     * and then later fail. In that case, timeout would pass as soon as times(2) passes, whereas after would run until
+     * times(2) failed, and then fail.
+     * <p>
+     * This feature should be used rarely - figure out a better way of testing your multi-threaded system.
+     * <pre class="code"><code class="java">
+     *   //passes when someMethod() is called within given time span
+     *   verify(mock, timeout(100)).someMethod();
+     *   //above is an alias to:
+     *   verify(mock, timeout(100).times(1)).someMethod();
+     *
+     *   //passes as soon as someMethod() has been called 2 times before the given timeout
+     *   verify(mock, timeout(100).times(2)).someMethod();
+     *
+     *   //equivalent: this also passes as soon as someMethod() has been called 2 times before the given timeout
+     *   verify(mock, timeout(100).atLeast(2)).someMethod();
+     *
+     *   //verifies someMethod() within given time span using given verification mode
+     *   //useful only if you have your own custom verification modes.
+     *   verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param millis - time span in milliseconds
+     *
+     * @return verification mode
+     */
+    public static VerificationWithTimeout timeout(long millis) {
+        return new Timeout(millis, VerificationModeFactory.times(1));
+    }
+
+    /**
+     * Allows verifying over a given period. It causes a verify to wait for a specified period of time for a desired
+     * interaction rather than failing immediately if has not already happened. May be useful for testing in concurrent
+     * conditions.
+     * <p>
+     * This differs from {@link Mockito#timeout timeout()} in that after() will wait the full period, whereas timeout()
+     * will stop early as soon as verification passes, producing different behaviour when used with times(2), for example,
+     * which can pass and then later fail. In that case, timeout would pass as soon as times(2) passes, whereas after would
+     * run the full time, which point it will fail, as times(2) has failed.
+     * <p>
+     * This feature should be used rarely - figure out a better way of testing your multi-threaded system.
+     * <p>
+     * Not yet implemented to work with InOrder verification.
+     * <pre class="code"><code class="java">
+     *   //passes after 100ms, if someMethod() has only been called once at that time.
+     *   verify(mock, after(100)).someMethod();
+     *   //above is an alias to:
+     *   verify(mock, after(100).times(1)).someMethod();
+     *
+     *   //passes if someMethod() is called <b>*exactly*</b> 2 times after the given timespan
+     *   verify(mock, after(100).times(2)).someMethod();
+     *
+     *   //passes if someMethod() has not been called after the given timespan
+     *   verify(mock, after(100).never()).someMethod();
+     *
+     *   //verifies someMethod() after a given time span using given verification mode
+     *   //useful only if you have your own custom verification modes.
+     *   verify(mock, new After(100, yourOwnVerificationMode)).someMethod();
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @param millis - time span in milliseconds
+     *
+     * @return verification mode
+     */
+    public static VerificationAfterDelay after(long millis) {
+        return new After(millis, VerificationModeFactory.times(1));
+    }
+
+    /**
+     * First of all, in case of any trouble, I encourage you to read the Mockito FAQ: <a href="https://github.com/mockito/mockito/wiki/FAQ">https://github.com/mockito/mockito/wiki/FAQ</a>
+     * <p>
+     * In case of questions you may also post to mockito mailing list: <a href="http://groups.google.com/group/mockito">http://groups.google.com/group/mockito</a>
+     * <p>
+     * <code>validateMockitoUsage()</code> <b>explicitly validates</b> the framework state to detect invalid use of Mockito.
+     * However, this feature is optional <b>because Mockito validates the usage all the time...</b> but there is a gotcha so read on.
+     * <p>
+     * Examples of incorrect use:
+     * <pre class="code"><code class="java">
+     * //Oops, thenReturn() part is missing:
+     * when(mock.get());
+     *
+     * //Oops, verified method call is inside verify() where it should be on the outside:
+     * verify(mock.execute());
+     *
+     * //Oops, missing method to verify:
+     * verify(mock);
+     * </code></pre>
+     *
+     * Mockito throws exceptions if you misuse it so that you know if your tests are written correctly.
+     * The gotcha is that Mockito does the validation <b>next time</b> you use the framework (e.g. next time you verify, stub, call mock etc.).
+     * But even though the exception might be thrown in the next test,
+     * the exception <b>message contains a navigable stack trace element</b> with location of the defect.
+     * Hence you can click and find the place where Mockito was misused.
+     * <p>
+     * Sometimes though, you might want to validate the framework usage explicitly.
+     * For example, one of the users wanted to put <code>validateMockitoUsage()</code> in his <code>&#064;After</code> method
+     * so that he knows immediately when he misused Mockito.
+     * Without it, he would have known about it not sooner than <b>next time</b> he used the framework.
+     * One more benefit of having <code>validateMockitoUsage()</code> in <code>&#064;After</code> is that jUnit runner and rule will always fail in the test method with defect
+     * whereas ordinary 'next-time' validation might fail the <b>next</b> test method.
+     * But even though JUnit might report next test as red, don't worry about it
+     * and just click at navigable stack trace element in the exception message to instantly locate the place where you misused mockito.
+     * <p>
+     * <b>Both built-in runner: {@link MockitoJUnitRunner} and rule: {@link MockitoRule}</b> do validateMockitoUsage() after each test method.
+     * <p>
+     * Bear in mind that <b>usually you don't have to <code>validateMockitoUsage()</code></b>
+     * and framework validation triggered on next-time basis should be just enough,
+     * mainly because of enhanced exception message with clickable location of defect.
+     * However, I would recommend validateMockitoUsage() if you already have sufficient test infrastructure
+     * (like your own runner or base class for all tests) because adding a special action to <code>&#064;After</code> has zero cost.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     */
+    public static void validateMockitoUsage() {
+        MOCKITO_CORE.validateMockitoUsage();
+    }
+
+    /**
+     * Allows mock creation with additional mock settings.
+     * <p>
+     * Don't use it too often.
+     * Consider writing simple tests that use simple mocks.
+     * Repeat after me: simple tests push simple, KISSy, readable & maintainable code.
+     * If you cannot write a test in a simple way - refactor the code under test.
+     * <p>
+     * Examples of mock settings:
+     * <pre class="code"><code class="java">
+     *   //Creates mock with different default answer & name
+     *   Foo mock = mock(Foo.class, withSettings()
+     *       .defaultAnswer(RETURNS_SMART_NULLS)
+     *       .name("cool mockie"));
+     *
+     *   //Creates mock with different default answer, descriptive name and extra interfaces
+     *   Foo mock = mock(Foo.class, withSettings()
+     *       .defaultAnswer(RETURNS_SMART_NULLS)
+     *       .name("cool mockie")
+     *       .extraInterfaces(Bar.class));
+     * </code></pre>
+     * {@link MockSettings} has been introduced for two reasons.
+     * Firstly, to make it easy to add another mock settings when the demand comes.
+     * Secondly, to enable combining different mock settings without introducing zillions of overloaded mock() methods.
+     * <p>
+     * See javadoc for {@link MockSettings} to learn about possible mock settings.
+     * <p>
+     *
+     * @return mock settings instance with defaults.
+     */
+    public static MockSettings withSettings() {
+        return new MockSettingsImpl().defaultAnswer(RETURNS_DEFAULTS);
+    }
+
+    /**
+     * Adds a description to be printed if verification fails.
+     * <pre class="code"><code class="java">
+     * verify(mock, description("This will print on failure")).someMethod("some arg");
+     * </code></pre>
+     * @param description The description to print on failure.
+     * @return verification mode
+     * @since 2.1.0
+     */
+    public static VerificationMode description(String description) {
+        return times(1).description(description);
+    }
+
+    /**
+     * @deprecated - please use {@link MockingDetails#printInvocations()}.
+     */
+    @Deprecated
+    static MockitoDebugger debug() {
+        return new MockitoDebuggerImpl();
+    }
+
+    /**
+     * For advanced users or framework integrators. See {@link MockitoFramework} class.
+     *
+     * @since 2.1.0
+     */
+    @Incubating
+    public static MockitoFramework framework() {
+        return new DefaultMockitoFramework();
+    }
+
+    /**
+     * {@code MockitoSession} is an optional, highly recommended feature
+     * that helps driving cleaner tests by eliminating boilerplate code and adding extra validation.
+     * <p>
+     * For more information, including use cases and sample code, see the javadoc for {@link MockitoSession}.
+     *
+     * @since 2.7.0
+     */
+    @Incubating
+    public static MockitoSessionBuilder mockitoSession() {
+        return new DefaultMockitoSessionBuilder();
+    }
+}
diff --git a/src/main/java/org/mockito/MockitoAnnotations.java b/src/main/java/org/mockito/MockitoAnnotations.java
index d02afa4..518a36f 100644
--- a/src/main/java/org/mockito/MockitoAnnotations.java
+++ b/src/main/java/org/mockito/MockitoAnnotations.java
@@ -5,48 +5,39 @@
 
 package org.mockito;
 
-import org.mockito.configuration.AnnotationEngine;
-import org.mockito.configuration.DefaultMockitoConfiguration;
-import org.mockito.exceptions.Reporter;
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.internal.configuration.GlobalConfiguration;
-import org.mockito.internal.util.reflection.FieldSetter;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Field;
-
-import static java.lang.annotation.ElementType.FIELD;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.plugins.AnnotationEngine;
 
 /**
  * MockitoAnnotations.initMocks(this); initializes fields annotated with Mockito annotations.
- * <p>  
+ * See also {@link MockitoSession} which not only initializes mocks
+ * but also adds extra validation for cleaner tests!
+ * <p>
  * <ul>
- * <li>Allows shorthand creation of objects required for testing.</li> 
- * <li>Minimizes repetitive mock creation code.</li> 
+ * <li>Allows shorthand creation of objects required for testing.</li>
+ * <li>Minimizes repetitive mock creation code.</li>
  * <li>Makes the test class more readable.</li>
  * <li>Makes the verification error easier to read because <b>field name</b> is used to identify the mock.</li>
  * </ul>
- * 
+ *
  * <pre class="code"><code class="java">
- *   public class ArticleManagerTest extends SampleBaseTestCase { 
- *     
+ *   public class ArticleManagerTest extends SampleBaseTestCase {
+ *
  *       &#064;Mock private ArticleCalculator calculator;
  *       &#064;Mock private ArticleDatabase database;
  *       &#064;Mock private UserProvider userProvider;
- *     
+ *
  *       private ArticleManager manager;
- *     
+ *
  *       &#064;Before public void setup() {
  *           manager = new ArticleManager(userProvider, database, calculator);
  *       }
  *   }
- *   
+ *
  *   public class SampleBaseTestCase {
- *   
+ *
  *       &#064;Before public void initMocks() {
  *           MockitoAnnotations.initMocks(this);
  *       }
@@ -57,32 +48,15 @@
  * <p>
  * <b><code>MockitoAnnotations.initMocks(this)</code></b> method has to called to initialize annotated fields.
  * <p>
- * In above example, <code>initMocks()</code> is called in &#064;Before (JUnit4) method of test's base class. 
+ * In above example, <code>initMocks()</code> is called in &#064;Before (JUnit4) method of test's base class.
  * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.
  * You can also put initMocks() in your JUnit runner (&#064;RunWith) or use built-in runner: {@link MockitoJUnitRunner}
  */
 public class MockitoAnnotations {
 
     /**
-     * Use top-level {@link org.mockito.Mock} annotation instead
-     * <p>
-     * When &#064;Mock annotation was implemented as an inner class then users experienced problems with autocomplete features in IDEs. 
-     * Hence &#064;Mock was made a top-level class.  
-     * <p>
-     * How to fix deprecation warnings? 
-     * Typically, you can just <b>search:</b> import org.mockito.MockitoAnnotations.Mock; <b>and replace with:</b> import org.mockito.Mock;
-     * <p>
-     * If you're an existing user then sorry for making your code littered with deprecation warnings. 
-     * This change was required to make Mockito better.
-     */
-    @Target( { FIELD })
-    @Retention(RetentionPolicy.RUNTIME)
-    @Deprecated
-    public @interface Mock {}    
-    
-    /**
      * Initializes objects annotated with Mockito annotations for given testClass:
-     *  &#064;{@link org.mockito.Mock}, &#064;{@link Spy}, &#064;{@link Captor}, &#064;{@link InjectMocks} 
+     *  &#064;{@link org.mockito.Mock}, &#064;{@link Spy}, &#064;{@link Captor}, &#064;{@link InjectMocks}
      * <p>
      * See examples in javadoc for {@link MockitoAnnotations} class.
      */
@@ -91,52 +65,7 @@
             throw new MockitoException("testClass cannot be null. For info how to use @Mock annotations see examples in javadoc for MockitoAnnotations class");
         }
 
-        AnnotationEngine annotationEngine = new GlobalConfiguration().getAnnotationEngine();
-        Class<?> clazz = testClass.getClass();
-
-        //below can be removed later, when we get read rid of deprecated stuff
-        if (annotationEngine.getClass() != new DefaultMockitoConfiguration().getAnnotationEngine().getClass()) {
-            //this means user has his own annotation engine and we have to respect that.
-            //we will do annotation processing the old way so that we are backwards compatible
-            while (clazz != Object.class) {
-                scanDeprecatedWay(annotationEngine, testClass, clazz);
-                clazz = clazz.getSuperclass();
-            }
-        }
-
-        //anyway act 'the new' way
+        AnnotationEngine annotationEngine = new GlobalConfiguration().tryGetPluginAnnotationEngine();
         annotationEngine.process(testClass.getClass(), testClass);
     }
-
-    static void scanDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Class<?> clazz) {
-        Field[] fields = clazz.getDeclaredFields();
-
-        for (Field field : fields) {
-            processAnnotationDeprecatedWay(annotationEngine, testClass, field);
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    static void processAnnotationDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Field field) {
-        boolean alreadyAssigned = false;
-        for(Annotation annotation : field.getAnnotations()) {
-            Object mock = annotationEngine.createMockFor(annotation, field);
-            if (mock != null) {
-                throwIfAlreadyAssigned(field, alreadyAssigned);
-                alreadyAssigned = true;                
-                try {
-                    new FieldSetter(testClass, field).set(mock);
-                } catch (Exception e) {
-                    throw new MockitoException("Problems setting field " + field.getName() + " annotated with "
-                            + annotation, e);
-                }
-            }
-        }
-    }
-
-    static void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) {
-        if (alreadyAssigned) {
-            new Reporter().moreThanOneAnnotationNotAllowed(field.getName());
-        }
-    }
 }
diff --git a/src/main/java/org/mockito/MockitoDebugger.java b/src/main/java/org/mockito/MockitoDebugger.java
index 496f3d7..cd29c18 100644
--- a/src/main/java/org/mockito/MockitoDebugger.java
+++ b/src/main/java/org/mockito/MockitoDebugger.java
@@ -2,12 +2,17 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito;

-

-public interface MockitoDebugger {

-

-    //Prints all interactions with mock. Also prints stubbing information.

-    //You can put it in your 'tearDown' method

-    String printInvocations(Object ... mocks);

-

-}
\ No newline at end of file
+package org.mockito;
+
+/**
+ * @deprecated - please use {@link MockingDetails#printInvocations()}.
+ */
+@Deprecated
+public interface MockitoDebugger {
+
+    /**
+     * @deprecated - please use {@link MockingDetails#printInvocations()}.
+     */
+    @Deprecated
+    String printInvocations(Object ... mocks);
+}
diff --git a/src/main/java/org/mockito/MockitoFramework.java b/src/main/java/org/mockito/MockitoFramework.java
new file mode 100644
index 0000000..73b8018
--- /dev/null
+++ b/src/main/java/org/mockito/MockitoFramework.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.exceptions.misusing.RedundantListenerException;
+import org.mockito.listeners.MockitoListener;
+
+/**
+ * Mockito framework settings and lifecycle listeners, for advanced users or for integrating with other frameworks.
+ * <p>
+ * To get <code>MockitoFramework</code> instance use {@link Mockito#framework()}.
+ * <p>
+ * For more info on listeners see {@link #addListener(MockitoListener)}.
+ *
+ * @since 2.1.0
+ */
+@Incubating
+public interface MockitoFramework {
+
+    /**
+     * Adds listener to Mockito.
+     * For a list of supported listeners, see the interfaces that extend {@link MockitoListener}.
+     * <p>
+     * Listeners can be useful for engs that extend Mockito framework.
+     * They are used in the implementation of unused stubbings warnings ({@link org.mockito.quality.MockitoHint}).
+     * <p>
+     * Make sure you remove the listener when the job is complete, see {@link #removeListener(MockitoListener)}.
+     * Currently the listeners list is thread local so you need to remove listener from the same thread otherwise
+     * remove is ineffectual.
+     * In typical scenarios, it is not a problem, because adding & removing listeners typically happens in the same thread.
+     * <p>
+     * If you are trying to add the listener but a listener of the same type was already added (and not removed)
+     * this method will throw {@link RedundantListenerException}.
+     * This is a safeguard to ensure users actually remove the listeners via {@link #removeListener(MockitoListener)}.
+     * We do not anticipate the use case where adding the same listener type multiple times is useful.
+     * If this safeguard is problematic, please contact us via Mockito issue tracker.
+     * <p>
+     * For usage examples, see Mockito codebase.
+     * If you have ideas and feature requests about Mockito listeners API
+     * we are very happy to hear about it via our issue tracker or mailing list.
+     *
+     * <pre class="code"><code class="java">
+     *   Mockito.framework().addListener(myListener);
+     * </code></pre>
+     *
+     * @param listener to add to Mockito
+     * @since 2.1.0
+     */
+    @Incubating
+    MockitoFramework addListener(MockitoListener listener) throws RedundantListenerException;
+
+    /**
+     * When you add listener using {@link #addListener(MockitoListener)} make sure to remove it.
+     * Currently the listeners list is thread local so you need to remove listener from the same thread otherwise
+     * remove is ineffectual.
+     * In typical scenarios, it is not a problem, because adding & removing listeners typically happens in the same thread.
+     * <p>
+     * For usage examples, see Mockito codebase.
+     * If you have ideas and feature requests about Mockito listeners API
+     * we are very happy to hear about it via our issue tracker or mailing list.
+     *
+     * @param listener to remove
+     * @since 2.1.0
+     */
+    @Incubating
+    MockitoFramework removeListener(MockitoListener listener);
+}
diff --git a/src/main/java/org/mockito/MockitoSession.java b/src/main/java/org/mockito/MockitoSession.java
new file mode 100644
index 0000000..5a34cb0
--- /dev/null
+++ b/src/main/java/org/mockito/MockitoSession.java
@@ -0,0 +1,108 @@
+package org.mockito;
+
+import org.mockito.exceptions.misusing.UnfinishedMockingSessionException;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+import org.mockito.listeners.MockitoListener;
+import org.mockito.quality.MockitoHint;
+import org.mockito.quality.Strictness;
+import org.mockito.session.MockitoSessionBuilder;
+
+/**
+ * {@code MockitoSession} is an optional, highly recommended feature
+ * that helps driving cleaner tests by eliminating boilerplate code and adding extra validation.
+ * If you already use {@link MockitoJUnitRunner} or {@link MockitoRule}
+ * *you don't need* {@code MockitoSession} because it is used by the runner/rule.
+ * <p>
+ * {@code MockitoSession} is a session of mocking, during which the user creates and uses Mockito mocks.
+ * Typically the session is an execution of a single test method.
+ * {@code MockitoSession} initializes mocks, validates usage and detects incorrect stubbing.
+ * When the session is started it must be concluded with {@link #finishMocking()}
+ * otherwise {@link UnfinishedMockingSessionException} is triggered when the next session is created.
+ * <p>
+ * {@code MockitoSession} is useful when you cannot use {@link MockitoJUnitRunner} or {@link MockitoRule}.
+ * For example, you work with TestNG instead of JUnit.
+ * Another example is when different JUnit runner is in use (Jukito, Springockito)
+ * and it cannot be combined with Mockito's own runner.
+ * <p>
+ * Framework integrators are welcome to use {@code MockitoSession} and give us feedback by commenting on
+ * <a href="https://github.com/mockito/mockito/issues/857">issue 857</a>.
+ * <p>
+ *
+ * Example:
+ * <pre class="code"><code class="java">
+ * public class ExampleTest {
+ *     &#064;Mock Foo foo;
+ *
+ *     //Keeping session object in a field so that we can complete session in 'tear down' method.
+ *     //It is recommended to hide the session object, along with 'setup' and 'tear down' methods in a base class / runner.
+ *     //Keep in mind that you can use Mockito's JUnit runner or rule instead of MockitoSession and get the same behavior.
+ *     MockitoSession mockito;
+ *
+ *     &#064;Before public void setup() {
+ *         //initialize session to start mocking
+ *         mockito = Mockito.mockitoSession()
+ *            .initMocks(this)
+ *            .strictness(Strictness.STRICT_STUBS)
+ *            .startMocking();
+ *     }
+ *
+ *     &#064;After public void tearDown() {
+ *         //It is necessary to finish the session so that Mockito
+ *         // can detect incorrect stubbing and validate Mockito usage
+ *         //'finishMocking()' is intended to be used in your test framework's 'tear down' method.
+ *         mockito.finishMocking();
+ *     }
+ *
+ *     // test methods ...
+ * }
+ * </code></pre>
+ *
+ * <p>
+ * Why to use {@code MockitoSession}?
+ * What's the difference between {@code MockitoSession}, {@link MockitoJUnitRunner}, {@link MockitoRule}
+ * and traditional {@link MockitoAnnotations#initMocks(Object)}?
+ * <p>
+ * Great questions!
+ * There is no need to use {@code MockitoSession} if you already use {@link MockitoJUnitRunner} or {@link MockitoRule}.
+ * If you are JUnit user who does not leverage Mockito rule or runner we strongly recommend to do so.
+ * Both the runner and the rule support strict stubbing which can really help driving cleaner tests.
+ * See {@link MockitoJUnitRunner.StrictStubs} and {@link MockitoRule#strictness(Strictness)}.
+ * If you cannot use Mockito's JUnit support (for example, you are on TestNG) {@code MockitoSession} exactly is for you!
+ * You can automatically take advantage of strict stubbing ({@link Strictness}),
+ * automatic initialization of annotated mocks ({@link MockitoAnnotations}),
+ * and extra validation ({@link Mockito#validateMockitoUsage()}).
+ * If you use Mockito annotations with {@link MockitoAnnotations#initMocks(Object)}
+ * but not Mockito runner/rule please try out Mockito's JUnit support (runner or rule) or
+ * start using {@code MockitoSession}. You'll get cleaner tests and better productivity.
+ * <p>
+ * Mockito team would really appreciate feedback about {@code MockitoSession} API.
+ * Help us out by commenting at <a href="https://github.com/mockito/mockito/issues/857">issue 857</a>.
+ *
+ * @since 2.7.0
+ */
+@Incubating
+public interface MockitoSession {
+
+    /**
+     * Must be invoked when the user is done with mocking for given session (test method).
+     * It detects unused stubbings and may throw {@link UnnecessaryStubbingException}
+     * or emit warnings ({@link MockitoHint}) depending on the {@link Strictness} level.
+     * The method also detects incorrect Mockito usage via {@link Mockito#validateMockitoUsage()}.
+     * <p>
+     * In order to implement {@link Strictness} Mockito session keeps track of mocking using {@link MockitoListener}.
+     * This method cleans up the listeners and ensures there is no leftover state after the session finishes.
+     * It is necessary to invoke this method to conclude mocking session.
+     * For more information about session lifecycle see {@link MockitoSessionBuilder#startMocking()}.
+     * <p>
+     * This method is intended to be used in your test framework's 'tear down' method.
+     * In the case of JUnit it is the "&#064;After" method.
+     * <p>
+     * For example, see javadoc for {@link MockitoSession}.
+     *
+     * @since 2.7.0
+     */
+    @Incubating
+    void finishMocking();
+}
diff --git a/src/main/java/org/mockito/ReturnValues.java b/src/main/java/org/mockito/ReturnValues.java
deleted file mode 100644
index f940212..0000000
--- a/src/main/java/org/mockito/ReturnValues.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito;
-
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-/**
- * @deprecated
- * <b>Instead, please use {@link Answer} interface</b>
- * <p>
- * In rare cases your code might not compile with recent deprecation & changes.
- * Very sorry for inconvenience but it had to be done in order to keep framework consistent.  
- * <p>
- * Why it is deprecated? ReturnValues is being replaced by Answer
- * for better consistency & interoperability of the framework. 
- * Answer interface has been in Mockito for a while and it has the same responsibility as ReturnValues.
- * There's no point in mainting exactly the same interfaces.
- * <p>
- * Configures return values for an unstubbed invocation
- * <p>
- * Can be used in {@link Mockito#mock(Class, ReturnValues)}
- */
-@Deprecated
-public interface ReturnValues {
-
-    /**
-     * return value for an unstubbed invocation
-     * 
-     * @param invocation placeholder for mock and a method
-     * @return the return value
-     */
-    Object valueFor(InvocationOnMock invocation) throws Throwable;
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/Spy.java b/src/main/java/org/mockito/Spy.java
index ec84c2e..6bb4609 100644
--- a/src/main/java/org/mockito/Spy.java
+++ b/src/main/java/org/mockito/Spy.java
@@ -1,109 +1,106 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito;

-

-import static java.lang.annotation.ElementType.FIELD;

-import static java.lang.annotation.RetentionPolicy.RUNTIME;

-import java.lang.annotation.Documented;

-import java.lang.annotation.Retention;

-import java.lang.annotation.Target;

-

-/**

- * Allows shorthand wrapping of field instances in an spy object.

- *

- * <p>

- * Example:

- *

- * <pre class="code"><code class="java">

- * public class Test{

- *    //Instance for spying is created by calling constructor explicitly:

- *    &#64;Spy Foo spyOnFoo = new Foo("argument");

- *    //Instance for spying is created by mockito via reflection (only default constructors supported):

- *    &#64;Spy Bar spyOnBar;

- *    &#64;Before

- *    public void init(){

- *       MockitoAnnotations.initMocks(this);

- *    }

- *    ...

- * }

- * </code></pre>

- * <p>

- * Same as doing:

- *

- * <pre class="code"><code class="java">

- * Foo spyOnFoo = Mockito.spy(new Foo("argument"));

- * Bar spyOnFoo = Mockito.spy(new Bar());

- * </code></pre>

- *

- * <p>

- * <strong>The field annotated with &#064;Spy can be initialized by Mockito if a zero argument constructor

- * can be found in the type (even private). <u>But Mockito cannot instantiate inner classes, local classes,

- * abstract classes and interfaces.</u></strong>

- *

- * <strong>The field annotated with &#064;Spy can be initialized explicitly at declaration point.

- * Alternatively, if you don't provide the instance Mockito will try to find zero argument constructor (even private)

- * and create an instance for you.

- * <u>But Mockito cannot instantiate inner classes, local classes, abstract classes and interfaces.</u></strong>

- *

- * For example this class can be instantiated by Mockito :

- * <pre class="code"><code class="java">public class Bar {

- *    private Bar() {}

- *    public Bar(String publicConstructorWithOneArg) {}

- * }</code></pre>

- * </p>

- *

- * <h4>Important gotcha on spying real objects!</h4>

- * <ol>

- * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.

- * Therefore for spies it is recommended to always use <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code>|<code>CallRealMethod</code>

- * family of methods for stubbing. Example:

- *

- * <pre class="code"><code class="java">

- *   List list = new LinkedList();

- *   List spy = spy(list);

- *

- *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)

- *   when(spy.get(0)).thenReturn("foo");

- *

- *   //You have to use doReturn() for stubbing

- *   doReturn("foo").when(spy).get(0);

- * </code></pre>

- * </li>

- *

- * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.

- * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction

- * and their effect on real instance state.

- * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,

- * you won't see any effects on the real instance.</li>

- *

- * <li>Watch out for final methods.

- * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.

- * Also you won't be able to verify those method as well.

- * </li>

- * </ol>

- *

- * <p>

- * <strong>One last warning :</strong> if you call <code>MockitoAnnotations.initMocks(this)</code> in a

- * super class <strong>constructor</strong> then this will not work. It is because fields

- * in subclass are only instantiated after super class constructor has returned.

- * It's better to use &#64;Before.

- * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (&#064;RunWith) or use the built-in

- * {@link org.mockito.runners.MockitoJUnitRunner}.

- * </p>

- *

- * <p>Note that the spy won't have any annotations of the spied type, because CGLIB won't rewrite them.

- * It may troublesome for code that rely on the spy to have these annotations.</p>

- *

- * @see Mockito#spy(Object)

- * @see Mock

- * @see InjectMocks

- * @see MockitoAnnotations#initMocks(Object)

- * @see org.mockito.runners.MockitoJUnitRunner

- * @since 1.8.3

- */

-@Retention(RUNTIME)

-@Target(FIELD)

-@Documented

-public @interface Spy { }

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import org.mockito.junit.MockitoJUnitRunner;
+
+/**
+ * Allows shorthand wrapping of field instances in an spy object.
+ *
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * public class Test{
+ *    //Instance for spying is created by calling constructor explicitly:
+ *    &#64;Spy Foo spyOnFoo = new Foo("argument");
+ *    //Instance for spying is created by mockito via reflection (only default constructors supported):
+ *    &#64;Spy Bar spyOnBar;
+ *    &#64;Before
+ *    public void init(){
+ *       MockitoAnnotations.initMocks(this);
+ *    }
+ *    ...
+ * }
+ * </code></pre>
+ * <p>
+ * Same as doing:
+ *
+ * <pre class="code"><code class="java">
+ * Foo spyOnFoo = Mockito.spy(new Foo("argument"));
+ * Bar spyOnBar = Mockito.spy(new Bar());
+ * </code></pre>
+ *
+ * <p>
+ * <strong>A field annotated with &#064;Spy can be initialized explicitly at declaration point.
+ * Alternatively, if you don't provide the instance Mockito will try to find zero argument constructor (even private)
+ * and create an instance for you.
+ * <u>But Mockito cannot instantiate inner classes, local classes, abstract classes and interfaces.</u></strong>
+ *
+ * For example this class can be instantiated by Mockito :
+ * <pre class="code"><code class="java">public class Bar {
+ *    private Bar() {}
+ *    public Bar(String publicConstructorWithOneArg) {}
+ * }</code></pre>
+ * </p>
+ *
+ * <h4>Important gotcha on spying real objects!</h4>
+ * <ol>
+ * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.
+ * Therefore for spies it is recommended to always use <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code>|<code>CallRealMethod</code>
+ * family of methods for stubbing. Example:
+ *
+ * <pre class="code"><code class="java">
+ *   List list = new LinkedList();
+ *   List spy = spy(list);
+ *
+ *   //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ *   when(spy.get(0)).thenReturn("foo");
+ *
+ *   //You have to use doReturn() for stubbing
+ *   doReturn("foo").when(spy).get(0);
+ * </code></pre>
+ * </li>
+ *
+ * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.
+ * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction
+ * and their effect on real instance state.
+ * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,
+ * you won't see any effects on the real instance.</li>
+ *
+ * <li>Watch out for final methods.
+ * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.
+ * Also you won't be able to verify those method as well.
+ * </li>
+ * </ol>
+ *
+ * <p>
+ * <strong>One last warning :</strong> if you call <code>MockitoAnnotations.initMocks(this)</code> in a
+ * super class <strong>constructor</strong> then this will not work. It is because fields
+ * in subclass are only instantiated after super class constructor has returned.
+ * It's better to use &#64;Before.
+ * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (&#064;RunWith) or use the built-in
+ * {@link MockitoJUnitRunner}.
+ * </p>
+ *
+ * <p>Note that the spy won't have any annotations of the spied type, because CGLIB won't rewrite them.
+ * It may troublesome for code that rely on the spy to have these annotations.</p>
+ *
+ * @see Mockito#spy(Object)
+ * @see Mock
+ * @see InjectMocks
+ * @see MockitoAnnotations#initMocks(Object)
+ * @see MockitoJUnitRunner
+ * @since 1.8.3
+ */
+@Retention(RUNTIME)
+@Target(FIELD)
+@Documented
+public @interface Spy { }
diff --git a/src/main/java/org/mockito/compat/ArgumentMatcher.java b/src/main/java/org/mockito/compat/ArgumentMatcher.java
index 915f603..a1d26fa 100644
--- a/src/main/java/org/mockito/compat/ArgumentMatcher.java
+++ b/src/main/java/org/mockito/compat/ArgumentMatcher.java
@@ -21,18 +21,17 @@
 /**
  * Base class for code that has to compile against Mockito 1.x and Mockito 2.x.
  */
-public abstract class ArgumentMatcher<T> extends org.mockito.ArgumentMatcher<T> {
+public abstract class ArgumentMatcher<T> implements org.mockito.ArgumentMatcher<T> {
 
     @Override
-    public boolean matches(Object argument) {
-      return matchesObject(argument);
+    public boolean matches(T argument) {
+        return matchesObject(argument);
     }
 
     public abstract boolean matchesObject(Object o);
 
-    @Override
-    public void describeTo(Description description) {
-        description.appendText(toString());
+    public final void describeTo(Description description) {
+      description.appendText(toString());
     }
 
     @Override
diff --git a/src/main/java/org/mockito/compat/CapturingMatcher.java b/src/main/java/org/mockito/compat/CapturingMatcher.java
index 4cf2468..782eff6 100644
--- a/src/main/java/org/mockito/compat/CapturingMatcher.java
+++ b/src/main/java/org/mockito/compat/CapturingMatcher.java
@@ -21,18 +21,16 @@
 /**
  * Base class for code that has to compile against Mockito 1.x and Mockito 2.x.
  */
-public abstract class CapturingMatcher<T>
-        extends org.mockito.internal.matchers.CapturingMatcher<T> {
+public abstract class CapturingMatcher<T> extends org.mockito.internal.matchers.CapturingMatcher<T> {
 
     @Override
     public boolean matches(Object argument) {
-      return matchesObject(argument);
+        return matchesObject(argument);
     }
 
     public abstract boolean matchesObject(Object o);
 
-    @Override
-    public void describeTo(Description description) {
+    public final void describeTo(Description description) {
         description.appendText(toString());
     }
 
diff --git a/src/main/java/org/mockito/configuration/AnnotationEngine.java b/src/main/java/org/mockito/configuration/AnnotationEngine.java
index ecd4461..40ff352 100644
--- a/src/main/java/org/mockito/configuration/AnnotationEngine.java
+++ b/src/main/java/org/mockito/configuration/AnnotationEngine.java
@@ -2,40 +2,27 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.configuration;

-

-import org.mockito.MockitoAnnotations;

-

-import java.lang.annotation.Annotation;

-import java.lang.reflect.Field;

-

-/**

- * Configures mock creation logic behind &#064;Mock, &#064;Captor and &#064;Spy annotations

- * <p>

- * If you are interested then see implementations or source code of {@link MockitoAnnotations#initMocks(Object)}

- */

-public interface AnnotationEngine {

-

-    /**

-     * @deprecated

-     * Please use {@link AnnotationEngine#process(Class, Object)} method instead that is more robust

-     * <p>

-     * Creates mock, ArgumentCaptor or wraps field instance in spy object.

-     * Only if of correct annotation type.

-     *

-     * @param annotation Annotation

-     * @param field Field details

-     */

-    @Deprecated

-    Object createMockFor(Annotation annotation, Field field);

-

-    /**

-     * Allows extending the interface to perform action on specific fields on the test class.

-     * <p>

-     * See the implementation of this method to figure out what is it for.

-     * 

-     * @param clazz Class where to extract field information, check implementation for details

-     * @param testInstance Test instance

-     */

-    void process(Class<?> clazz, Object testInstance);

-}
\ No newline at end of file
+package org.mockito.configuration;
+
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Configures mock creation logic behind &#064;Mock, &#064;Captor and &#064;Spy annotations
+ * <p>
+ * If you are interested then see implementations or source code of {@link MockitoAnnotations#initMocks(Object)}
+ *
+ * <p>This interface can be used to configure a different annotation engine through
+ * {@link org.mockito.configuration.IMockitoConfiguration}, however this mechanism is being superseded by the new
+ * {@link org.mockito.plugins plugin} system.
+ *
+ * <p>
+ * Note that if it exists on the classpath both a class <code>org.mockito.configuration.MockitoConfiguration</code>
+ * and a file <code>mockito-extensions/org.mockito.plugins.AnnotationEngine</code> then the implementation of
+ * <code>org.mockito.configuration.MockitoConfiguration</code> will be chosen instead of the one in the file.
+
+ * @deprecated Please use {@link org.mockito.plugins.AnnotationEngine} instead,
+ *             this interface will probably be removed in mockito 3.
+ */
+@Deprecated
+public interface AnnotationEngine extends org.mockito.plugins.AnnotationEngine {
+}
diff --git a/src/main/java/org/mockito/configuration/DefaultMockitoConfiguration.java b/src/main/java/org/mockito/configuration/DefaultMockitoConfiguration.java
index 626e457..cad13e7 100644
--- a/src/main/java/org/mockito/configuration/DefaultMockitoConfiguration.java
+++ b/src/main/java/org/mockito/configuration/DefaultMockitoConfiguration.java
@@ -1,57 +1,46 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.configuration;

-

-import org.mockito.ReturnValues;

-import org.mockito.internal.configuration.InjectingAnnotationEngine;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;

-import org.mockito.stubbing.Answer;

-

-/**

- * DefaultConfiguration of Mockito framework

- * <p>

- * Currently it doesn't have many configuration options but it will probably change if future.

- * <p>

- * See javadocs for {@link IMockitoConfiguration} on info how to configure Mockito

- */

-@SuppressWarnings("deprecation")//suppressed until ReturnValues are removed

-public class DefaultMockitoConfiguration implements IMockitoConfiguration {

-    

-    /* (non-Javadoc)

-     * @see org.mockito.IMockitoConfiguration#getReturnValues()

-     */

-    @Deprecated

-    public ReturnValues getReturnValues() {

-        throw new RuntimeException("\n" + "This method should not be used by the framework because it was deprecated"

-                + "\n" + "Please report the failure to the Mockito mailing list");

-    }

-

-    public Answer<Object> getDefaultAnswer() {

-        return new ReturnsEmptyValues();

-    }

-    

-    /* (non-Javadoc)

-     * @see org.mockito.IMockitoConfiguration#getAnnotationEngine()

-     */

-    public AnnotationEngine getAnnotationEngine() {

-        return new InjectingAnnotationEngine();

-    }

-

-    /* (non-Javadoc)

-     * @see org.mockito.configuration.IMockitoConfiguration#cleansStackTrace()

-     */

-    public boolean cleansStackTrace() {

-        return true;

-    }

-

-    /* (non-Javadoc)

-     * @see org.mockito.configuration.IMockitoConfiguration#enableClassCache()

-     */

-    public boolean enableClassCache() {

-        return true;

-    }

-    

-    

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.configuration;
+
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.stubbing.Answer;
+
+/**
+ * DefaultConfiguration of Mockito framework
+ * <p>
+ * Currently it doesn't have many configuration options but it will probably change if future.
+ * <p>
+ * See javadocs for {@link IMockitoConfiguration} on info how to configure Mockito
+ */
+public class DefaultMockitoConfiguration implements IMockitoConfiguration {
+
+    public Answer<Object> getDefaultAnswer() {
+        return new ReturnsEmptyValues();
+    }
+
+    /* (non-Javadoc)
+     * @see org.mockito.IMockitoConfiguration#getAnnotationEngine()
+     */
+    public AnnotationEngine getAnnotationEngine() {
+        return new InjectingAnnotationEngine();
+    }
+
+    /* (non-Javadoc)
+     * @see org.mockito.configuration.IMockitoConfiguration#cleansStackTrace()
+     */
+    public boolean cleansStackTrace() {
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.mockito.configuration.IMockitoConfiguration#enableClassCache()
+     */
+    public boolean enableClassCache() {
+        return true;
+    }
+
+
+}
diff --git a/src/main/java/org/mockito/configuration/IMockitoConfiguration.java b/src/main/java/org/mockito/configuration/IMockitoConfiguration.java
index 4767d57..2c2da56 100644
--- a/src/main/java/org/mockito/configuration/IMockitoConfiguration.java
+++ b/src/main/java/org/mockito/configuration/IMockitoConfiguration.java
@@ -1,84 +1,81 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.configuration;

-

-import org.mockito.ReturnValues;

-import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;

-import org.mockito.stubbing.Answer;

-

-/**

- * Use it to configure Mockito. For now there are not many configuration options but it may change in future.

- * <p>

- * In most cases you don't really need to configure Mockito. For example in case of working with legacy code, 

- * when you might want to have different 'mocking style' this interface might be helpful. 

- * A reason of configuring Mockito might be if you disagree with the {@link ReturnsEmptyValues} unstubbed mocks return.

- * <p>

- * To configure Mockito create exactly <b>org.mockito.configuration.MockitoConfiguration</b> class that implements this interface.

- * <p>

- * Configuring Mockito is completely <b>optional</b> - nothing happens if there isn't any <b>org.mockito.configuration.MockitoConfiguration</b> on the classpath. 

- * <p>

- * <b>org.mockito.configuration.MockitoConfiguration</b> must implement IMockitoConfiguration or extend {@link DefaultMockitoConfiguration}

- * <p>

- * Mockito will store single instance of org.mockito.configuration.MockitoConfiguration per thread (using ThreadLocal). 

- * For sanity of your tests, don't make the implementation stateful.

- * <p>

- * If you have comments on Mockito configuration feature don't hesitate to write to mockito@googlegroups.com

- */

-@SuppressWarnings("deprecation")//suppressed until ReturnValues are removed

-public interface IMockitoConfiguration {

-

-    /**

-     * @deprecated

-     * <b>Please use {@link IMockitoConfiguration#getDefaultAnswer()}</b>

-     * <p>

-     * Steps: 

-     * <p>

-     * 1. Leave the implementation of getReturnValues() method empty - it's not going to be used anyway.

-     * <p>

-     * 2. Implement getDefaultAnswer() instead.

-     * <p>

-     * In rare cases your code might not compile with recent deprecation & changes.

-     * Very sorry for inconvenience but it had to be done in order to keep framework consistent.

-     * <p>

-     * See javadoc {@link ReturnValues} for info why this method was deprecated

-     * <p>

-     * Allows configuring the default return values of unstubbed invocations

-     * <p>

-     * See javadoc for {@link IMockitoConfiguration}

-     */

-    @Deprecated

-    ReturnValues getReturnValues();

-    

-    /**

-     * Allows configuring the default answers of unstubbed invocations

-     * <p>

-     * See javadoc for {@link IMockitoConfiguration}

-     */    

-    Answer<Object> getDefaultAnswer();

-

-    /**

-     * Configures annotations for mocks

-     * <p>

-     * See javadoc for {@link IMockitoConfiguration}

-     */

-    AnnotationEngine getAnnotationEngine();

-

-    /**

-     * This should be turned on unless you're a Mockito developer and you wish

-     * to have verbose (read: messy) stack traces that only few understand (eg:

-     * Mockito developers)

-     * <p>

-     * See javadoc for {@link IMockitoConfiguration}

-     * 

-     * @return if Mockito should clean stack traces

-     */

-    boolean cleansStackTrace();

-    

-    /**

-     * Allow objenesis to cache classes. If you're in an environment where classes 

-     * are dynamically reloaded, you can disable this to avoid classcast exceptions.

-     */

-    boolean enableClassCache();

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.configuration;
+
+import org.mockito.stubbing.Answer;
+
+/**
+ * Use it to configure Mockito. For now there are not many configuration options but it may change in future.
+ *
+ * <p>
+ * In most cases you don't really need to configure Mockito. For example in case of working with legacy code,
+ * when you might want to have different 'mocking style' this interface might be helpful.
+ * A reason of configuring Mockito might be if you disagree with the {@link org.mockito.Answers#RETURNS_DEFAULTS}
+ * unstubbed mocks return.
+ *
+ * <p>
+ * To configure Mockito create exactly <b>org.mockito.configuration.MockitoConfiguration</b> class
+ * that implements this interface.
+ *
+ * <p>
+ * Configuring Mockito is completely <b>optional</b> - nothing happens if there isn't any
+ * <b>org.mockito.configuration.MockitoConfiguration</b> on the classpath.
+ *
+ * <p>
+ * <b>org.mockito.configuration.MockitoConfiguration</b> must implement <code>IMockitoConfiguration</code> or
+ * extend {@link DefaultMockitoConfiguration}
+ *
+ * <p>
+ * Mockito will store single instance of <code>org.mockito.configuration.MockitoConfiguration</code>
+ * per thread (using <code>ThreadLocal</code>).
+ * For sanity of your tests, don't make the implementation stateful.
+ *
+ * <p>
+ * If you have comments on Mockito configuration feature don't hesitate to write to mockito@googlegroups.com.
+ */
+public interface IMockitoConfiguration {
+
+    /**
+     * Allows configuring the default answers of unstubbed invocations
+     * <p>
+     * See javadoc for {@link IMockitoConfiguration}
+     */
+    Answer<Object> getDefaultAnswer();
+
+    /**
+     * Configures annotations for mocks.
+     *
+     * <p>
+     * This method will have lower priority that the new extension mechanism.
+     * That is if it exists on the classpath both a class <code>org.mockito.configuration.MockitoConfiguration</code>
+     * and a file <code>mockito-extensions/org.mockito.plugins.AnnotationEngine</code> then the implementation of
+     * <code>org.mockito.configuration.MockitoConfiguration</code> will be chosen instead of the one in the file.
+     *
+     * <p>
+     * See javadoc for {@link IMockitoConfiguration}
+     *
+     * @deprecated Please use the extension mechanism {@link org.mockito.plugins.AnnotationEngine} instead,
+     *             this method will probably be removed in mockito 3.
+     */
+    @Deprecated
+    AnnotationEngine getAnnotationEngine();
+
+    /**
+     * This should be turned on unless you're a Mockito developer and you wish
+     * to have verbose (read: messy) stack traces that only few understand (eg:
+     * Mockito developers)
+     * <p>
+     * See javadoc for {@link IMockitoConfiguration}
+     *
+     * @return if Mockito should clean stack traces
+     */
+    boolean cleansStackTrace();
+
+    /**
+     * Allow objenesis to cache classes. If you're in an environment where classes
+     * are dynamically reloaded, you can disable this to avoid classcast exceptions.
+     */
+    boolean enableClassCache();
+}
diff --git a/src/main/java/org/mockito/configuration/package-info.java b/src/main/java/org/mockito/configuration/package-info.java
new file mode 100644
index 0000000..b816f9b
--- /dev/null
+++ b/src/main/java/org/mockito/configuration/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito configuration utilities.
+ */
+package org.mockito.configuration;
diff --git a/src/main/java/org/mockito/configuration/package.html b/src/main/java/org/mockito/configuration/package.html
deleted file mode 100644
index b4bec23..0000000
--- a/src/main/java/org/mockito/configuration/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Mockito configuration utilities
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/Discrepancy.java b/src/main/java/org/mockito/exceptions/Discrepancy.java
deleted file mode 100644
index 570c469..0000000
--- a/src/main/java/org/mockito/exceptions/Discrepancy.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.exceptions;

-

-@Deprecated

-/**

- * @Deprecated. This class has been moved to internal packages because it was never meant to be public.

- * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.reporting.Discrepancy}.

- * However, the package clearly states that the class in a part of a public API so it can change.

- */

-public class Discrepancy extends org.mockito.internal.reporting.Discrepancy {

-    public Discrepancy(int wantedCount, int actualCount) {

-        super(wantedCount, actualCount);

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/Pluralizer.java b/src/main/java/org/mockito/exceptions/Pluralizer.java
deleted file mode 100644
index 8fdad39..0000000
--- a/src/main/java/org/mockito/exceptions/Pluralizer.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.exceptions;

-

-@Deprecated

-/**

- * @Deprecated. This class has been moved to internal packages because it was never meant to be public.

- * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.reporting.Pluralizer}.

- * However, the package clearly states that the class in a part of a public API so it can change.

- */

-public class Pluralizer extends org.mockito.internal.reporting.Pluralizer {}

diff --git a/src/main/java/org/mockito/exceptions/PrintableInvocation.java b/src/main/java/org/mockito/exceptions/PrintableInvocation.java
deleted file mode 100644
index 52e288d..0000000
--- a/src/main/java/org/mockito/exceptions/PrintableInvocation.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.exceptions;
-
-import org.mockito.invocation.DescribedInvocation;
-import org.mockito.invocation.Location;
-
-@Deprecated
-/**
- * @Deprecated. We needed to move this class to a better place to keep consistency of the API.
- * Please use {@link DescribedInvocation} instead.
- */
-public interface PrintableInvocation {
-
-    String toString();
-
-    Location getLocation();
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/Reporter.java b/src/main/java/org/mockito/exceptions/Reporter.java
deleted file mode 100644
index 7ae7588..0000000
--- a/src/main/java/org/mockito/exceptions/Reporter.java
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.exceptions;
-
-import org.mockito.exceptions.base.MockitoAssertionError;
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.exceptions.misusing.*;
-import org.mockito.exceptions.verification.*;
-import org.mockito.internal.debugging.LocationImpl;
-import org.mockito.internal.exceptions.MockitoLimitations;
-import org.mockito.internal.exceptions.VerificationAwareInvocation;
-import org.mockito.internal.exceptions.util.ScenarioPrinter;
-import org.mockito.internal.junit.JUnitTool;
-import org.mockito.internal.matchers.LocalizedMatcher;
-import org.mockito.internal.util.MockUtil;
-import org.mockito.internal.util.StringJoiner;
-import org.mockito.invocation.DescribedInvocation;
-import org.mockito.invocation.Invocation;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.invocation.Location;
-import org.mockito.listeners.InvocationListener;
-import org.mockito.mock.SerializableMode;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import static org.mockito.internal.reporting.Pluralizer.pluralize;
-import static org.mockito.internal.util.StringJoiner.join;
-
-/**
- * Reports verification and misusing errors.
- * <p>
- * One of the key points of mocking library is proper verification/exception
- * messages. All messages in one place makes it easier to tune and amend them.
- * <p>
- * Reporter can be injected and therefore is easily testable.
- * <p>
- * Generally, exception messages are full of line breaks to make them easy to
- * read (xunit plugins take only fraction of screen on modern IDEs).
- */
-public class Reporter {
-
-    public void checkedExceptionInvalid(Throwable t) {
-        throw new MockitoException(join(
-                "Checked exception is invalid for this method!",
-                "Invalid: " + t
-        ));
-    }
-
-    public void cannotStubWithNullThrowable() {
-        throw new MockitoException(join(
-                "Cannot stub with null throwable!"
-        ));
-
-    }
-
-    public void unfinishedStubbing(Location location) {
-        throw new UnfinishedStubbingException(join(
-                "Unfinished stubbing detected here:",
-                location,
-                "",
-                "E.g. thenReturn() may be missing.",
-                "Examples of correct stubbing:",
-                "    when(mock.isOk()).thenReturn(true);",
-                "    when(mock.isOk()).thenThrow(exception);",
-                "    doThrow(exception).when(mock).someVoidMethod();",
-                "Hints:",
-                " 1. missing thenReturn()",
-                " 2. you are trying to stub a final method, you naughty developer!",
-                " 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed",
-                ""
-        ));
-    }
-
-    public void incorrectUseOfApi() {
-        throw new MockitoException(join(
-                "Incorrect use of API detected here:",
-                new LocationImpl(),
-                "",
-                "You probably stored a reference to OngoingStubbing returned by when() and called stubbing methods like thenReturn() on this reference more than once.",
-                "Examples of correct usage:",
-                "    when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);",
-                "    when(mock.isOk()).thenReturn(true, false).thenThrow(exception);",
-                ""
-        ));
-    }
-
-    public void missingMethodInvocation() {
-        throw new MissingMethodInvocationException(join(
-                "when() requires an argument which has to be 'a method call on a mock'.",
-                "For example:",
-                "    when(mock.getArticles()).thenReturn(articles);",
-                "",
-                "Also, this error might show up because:",
-                "1. you stub either of: final/private/equals()/hashCode() methods.",
-                "   Those methods *cannot* be stubbed/verified.",
-                "   " + MockitoLimitations.NON_PUBLIC_PARENT,
-                "2. inside when() you don't call method on mock but on some other object.",
-                ""
-        ));
-    }
-
-    public void unfinishedVerificationException(Location location) {
-        UnfinishedVerificationException exception = new UnfinishedVerificationException(join(
-                "Missing method call for verify(mock) here:",
-                location,
-                "",
-                "Example of correct verification:",
-                "    verify(mock).doSomething()",
-                "",
-                "Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.",
-                "Those methods *cannot* be stubbed/verified.",
-                MockitoLimitations.NON_PUBLIC_PARENT,
-                ""
-        ));
-
-        throw exception;
-    }
-
-    public void notAMockPassedToVerify(Class type) {
-        throw new NotAMockException(join(
-                "Argument passed to verify() is of type " + type.getSimpleName() + " and is not a mock!",
-                "Make sure you place the parenthesis correctly!",
-                "See the examples of correct verifications:",
-                "    verify(mock).someMethod();",
-                "    verify(mock, times(10)).someMethod();",
-                "    verify(mock, atLeastOnce()).someMethod();"
-        ));
-    }
-
-    public void nullPassedToVerify() {
-        throw new NullInsteadOfMockException(join(
-                "Argument passed to verify() should be a mock but is null!",
-                "Examples of correct verifications:",
-                "    verify(mock).someMethod();",
-                "    verify(mock, times(10)).someMethod();",
-                "    verify(mock, atLeastOnce()).someMethod();",
-                "    not: verify(mock.someMethod());",
-                "Also, if you use @Mock annotation don't miss initMocks()"
-        ));
-    }
-
-    public void notAMockPassedToWhenMethod() {
-        throw new NotAMockException(join(
-                "Argument passed to when() is not a mock!",
-                "Example of correct stubbing:",
-                "    doThrow(new RuntimeException()).when(mock).someMethod();"
-        ));
-    }
-
-    public void nullPassedToWhenMethod() {
-        throw new NullInsteadOfMockException(join(
-                "Argument passed to when() is null!",
-                "Example of correct stubbing:",
-                "    doThrow(new RuntimeException()).when(mock).someMethod();",
-                "Also, if you use @Mock annotation don't miss initMocks()"
-        ));
-    }
-
-    public void mocksHaveToBePassedToVerifyNoMoreInteractions() {
-        throw new MockitoException(join(
-                "Method requires argument(s)!",
-                "Pass mocks that should be verified, e.g:",
-                "    verifyNoMoreInteractions(mockOne, mockTwo);",
-                "    verifyZeroInteractions(mockOne, mockTwo);",
-                ""
-        ));
-    }
-
-    public void notAMockPassedToVerifyNoMoreInteractions() {
-        throw new NotAMockException(join(
-                "Argument(s) passed is not a mock!",
-                "Examples of correct verifications:",
-                "    verifyNoMoreInteractions(mockOne, mockTwo);",
-                "    verifyZeroInteractions(mockOne, mockTwo);",
-                ""
-        ));
-    }
-
-    public void nullPassedToVerifyNoMoreInteractions() {
-        throw new NullInsteadOfMockException(join(
-                "Argument(s) passed is null!",
-                "Examples of correct verifications:",
-                "    verifyNoMoreInteractions(mockOne, mockTwo);",
-                "    verifyZeroInteractions(mockOne, mockTwo);"
-        ));
-    }
-
-    public void notAMockPassedWhenCreatingInOrder() {
-        throw new NotAMockException(join(
-                "Argument(s) passed is not a mock!",
-                "Pass mocks that require verification in order.",
-                "For example:",
-                "    InOrder inOrder = inOrder(mockOne, mockTwo);"
-        ));
-    }
-
-    public void nullPassedWhenCreatingInOrder() {
-        throw new NullInsteadOfMockException(join(
-                "Argument(s) passed is null!",
-                "Pass mocks that require verification in order.",
-                "For example:",
-                "    InOrder inOrder = inOrder(mockOne, mockTwo);"
-        ));
-    }
-
-    public void mocksHaveToBePassedWhenCreatingInOrder() {
-        throw new MockitoException(join(
-                "Method requires argument(s)!",
-                "Pass mocks that require verification in order.",
-                "For example:",
-                "    InOrder inOrder = inOrder(mockOne, mockTwo);"
-        ));
-    }
-
-    public void inOrderRequiresFamiliarMock() {
-        throw new MockitoException(join(
-                "InOrder can only verify mocks that were passed in during creation of InOrder.",
-                "For example:",
-                "    InOrder inOrder = inOrder(mockOne);",
-                "    inOrder.verify(mockOne).doStuff();"
-        ));
-    }
-
-    public void invalidUseOfMatchers(int expectedMatchersCount, List<LocalizedMatcher> recordedMatchers) {
-        throw new InvalidUseOfMatchersException(join(
-                "Invalid use of argument matchers!",
-                expectedMatchersCount + " matchers expected, " + recordedMatchers.size()+ " recorded:" +
-                        locationsOf(recordedMatchers),
-                "",
-                "This exception may occur if matchers are combined with raw values:",
-                "    //incorrect:",
-                "    someMethod(anyObject(), \"raw String\");",
-                "When using matchers, all arguments have to be provided by matchers.",
-                "For example:",
-                "    //correct:",
-                "    someMethod(anyObject(), eq(\"String by matcher\"));",
-                "",
-                "For more info see javadoc for Matchers class.",
-                ""
-        ));
-    }
-
-    public void incorrectUseOfAdditionalMatchers(String additionalMatcherName, int expectedSubMatchersCount, Collection<LocalizedMatcher> matcherStack) {
-        throw new InvalidUseOfMatchersException(join(
-                "Invalid use of argument matchers inside additional matcher " + additionalMatcherName + " !",
-                new LocationImpl(),
-                "",
-                expectedSubMatchersCount + " sub matchers expected, " + matcherStack.size() + " recorded:",
-                locationsOf(matcherStack),
-                "",
-                "This exception may occur if matchers are combined with raw values:",
-                "    //incorrect:",
-                "    someMethod(AdditionalMatchers.and(isNotNull(), \"raw String\");",
-                "When using matchers, all arguments have to be provided by matchers.",
-                "For example:",
-                "    //correct:",
-                "    someMethod(AdditionalMatchers.and(isNotNull(), eq(\"raw String\"));",
-                "",
-                "For more info see javadoc for Matchers and AdditionalMatchers classes.",
-                ""
-        ));
-    }
-
-    public void stubPassedToVerify() {
-        throw new CannotVerifyStubOnlyMock(join(
-                "Argument passed to verify() is a stubOnly() mock, not a full blown mock!",
-                "If you intend to verify invocations on a mock, don't use stubOnly() in its MockSettings."
-        ));
-    }
-
-    public void reportNoSubMatchersFound(String additionalMatcherName) {
-        throw new InvalidUseOfMatchersException(join(
-                "No matchers found for additional matcher " + additionalMatcherName,
-                new LocationImpl(),
-                ""
-        ));
-    }
-
-
-    private Object locationsOf(Collection<LocalizedMatcher> matchers) {
-        List<String> description = new ArrayList<String>();
-        for (LocalizedMatcher matcher : matchers)
-            description.add(matcher.getLocation().toString());
-        return join(description.toArray());
-    }
-
-    public void argumentsAreDifferent(String wanted, String actual, Location actualLocation) {
-        String message = join("Argument(s) are different! Wanted:",
-                wanted,
-                new LocationImpl(),
-                "Actual invocation has different arguments:",
-                actual,
-                actualLocation,
-                ""
-        );
-
-        throw JUnitTool.createArgumentsAreDifferentException(message, wanted, actual);
-    }
-
-    public void wantedButNotInvoked(DescribedInvocation wanted) {
-        throw new WantedButNotInvoked(createWantedButNotInvokedMessage(wanted));
-    }
-
-    public void wantedButNotInvoked(DescribedInvocation wanted, List<? extends DescribedInvocation> invocations) {
-        String allInvocations;
-        if (invocations.isEmpty()) {
-            allInvocations = "Actually, there were zero interactions with this mock.\n";
-        } else {
-            StringBuilder sb = new StringBuilder("\nHowever, there were other interactions with this mock:\n");
-            for (DescribedInvocation i : invocations) {
-                sb.append(i.toString())
-                        .append("\n")
-                        .append(i.getLocation())
-                        .append("\n\n");
-            }
-            allInvocations = sb.toString();
-        }
-
-        String message = createWantedButNotInvokedMessage(wanted);
-        throw new WantedButNotInvoked(message + allInvocations);
-    }
-
-    private String createWantedButNotInvokedMessage(DescribedInvocation wanted) {
-        return join(
-                "Wanted but not invoked:",
-                wanted.toString(),
-                new LocationImpl(),
-                ""
-        );
-    }
-
-    public void wantedButNotInvokedInOrder(DescribedInvocation wanted, DescribedInvocation previous) {
-        throw new VerificationInOrderFailure(join(
-                "Verification in order failure",
-                "Wanted but not invoked:",
-                wanted.toString(),
-                new LocationImpl(),
-                "Wanted anywhere AFTER following interaction:",
-                previous.toString(),
-                previous.getLocation(),
-                ""
-        ));
-    }
-
-    public void tooManyActualInvocations(int wantedCount, int actualCount, DescribedInvocation wanted, Location firstUndesired) {
-        String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, firstUndesired);
-        throw new TooManyActualInvocations(message);
-    }
-
-    private String createTooManyInvocationsMessage(int wantedCount, int actualCount, DescribedInvocation wanted,
-                                                   Location firstUndesired) {
-        return join(
-                wanted.toString(),
-                "Wanted " + pluralize(wantedCount) + ":",
-                new LocationImpl(),
-                "But was " + pluralize(actualCount) + ". Undesired invocation:",
-                firstUndesired,
-                ""
-        );
-    }
-
-    public void neverWantedButInvoked(DescribedInvocation wanted, Location firstUndesired) {
-        throw new NeverWantedButInvoked(join(
-                wanted.toString(),
-                "Never wanted here:",
-                new LocationImpl(),
-                "But invoked here:",
-                firstUndesired,
-                ""
-        ));
-    }
-
-    public void tooManyActualInvocationsInOrder(int wantedCount, int actualCount, DescribedInvocation wanted, Location firstUndesired) {
-        String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, firstUndesired);
-        throw new VerificationInOrderFailure(join(
-                "Verification in order failure:" + message
-        ));
-    }
-
-    private String createTooLittleInvocationsMessage(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted,
-                                                     Location lastActualInvocation) {
-        String ending =
-                (lastActualInvocation != null)? lastActualInvocation + "\n" : "\n";
-
-        String message = join(
-                wanted.toString(),
-                "Wanted " + discrepancy.getPluralizedWantedCount() + ":",
-                new LocationImpl(),
-                "But was " + discrepancy.getPluralizedActualCount() + ":",
-                ending
-        );
-        return message;
-    }
-
-    public void tooLittleActualInvocations(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, Location lastActualLocation) {
-        String message = createTooLittleInvocationsMessage(discrepancy, wanted, lastActualLocation);
-
-        throw new TooLittleActualInvocations(message);
-    }
-
-    public void tooLittleActualInvocationsInOrder(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, Location lastActualLocation) {
-        String message = createTooLittleInvocationsMessage(discrepancy, wanted, lastActualLocation);
-
-        throw new VerificationInOrderFailure(join(
-                "Verification in order failure:" + message
-        ));
-    }
-
-    public void noMoreInteractionsWanted(Invocation undesired, List<VerificationAwareInvocation> invocations) {
-        ScenarioPrinter scenarioPrinter = new ScenarioPrinter();
-        String scenario = scenarioPrinter.print(invocations);
-
-        throw new NoInteractionsWanted(join(
-                "No interactions wanted here:",
-                new LocationImpl(),
-                "But found this interaction on mock '" + undesired.getMock() + "':",
-                undesired.getLocation(),
-                scenario
-        ));
-    }
-
-    public void noMoreInteractionsWantedInOrder(Invocation undesired) {
-        throw new VerificationInOrderFailure(join(
-                "No interactions wanted here:",
-                new LocationImpl(),
-                "But found this interaction on mock '" + undesired.getMock() + "':",
-                undesired.getLocation()
-        ));
-    }
-
-    public void cannotMockFinalClass(Class<?> clazz) {
-        throw new MockitoException(join(
-                "Cannot mock/spy " + clazz.toString(),
-                "Mockito cannot mock/spy following:",
-                "  - final classes",
-                "  - anonymous classes",
-                "  - primitive types"
-        ));
-    }
-
-    public void cannotStubVoidMethodWithAReturnValue(String methodName) {
-        throw new CannotStubVoidMethodWithReturnValue(join(
-                "'" + methodName + "' is a *void method* and it *cannot* be stubbed with a *return value*!",
-                "Voids are usually stubbed with Throwables:",
-                "    doThrow(exception).when(mock).someVoidMethod();",
-                "***",
-                "If you're unsure why you're getting above error read on.",
-                "Due to the nature of the syntax above problem might occur because:",
-                "1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.",
-                "2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.",
-                "3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
-                "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
-                "4. " + MockitoLimitations.NON_PUBLIC_PARENT,
-                ""
-        ));
-    }
-
-    public void onlyVoidMethodsCanBeSetToDoNothing() {
-        throw new MockitoException(join(
-                "Only void methods can doNothing()!",
-                "Example of correct use of doNothing():",
-                "    doNothing().",
-                "    doThrow(new RuntimeException())",
-                "    .when(mock).someVoidMethod();",
-                "Above means:",
-                "someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called"
-        ));
-    }
-
-    public void wrongTypeOfReturnValue(String expectedType, String actualType, String methodName) {
-        throw new WrongTypeOfReturnValue(join(
-                actualType + " cannot be returned by " + methodName + "()",
-                methodName + "() should return " + expectedType,
-                "***",
-                "If you're unsure why you're getting above error read on.",
-                "Due to the nature of the syntax above problem might occur because:",
-                "1. This exception *might* occur in wrongly written multi-threaded tests.",
-                "   Please refer to Mockito FAQ on limitations of concurrency testing.",
-                "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
-                "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
-                ""
-        ));
-    }
-
-    public void wantedAtMostX(int maxNumberOfInvocations, int foundSize) {
-        throw new MockitoAssertionError(join("Wanted at most " + pluralize(maxNumberOfInvocations) + " but was " + foundSize));
-    }
-
-    public void misplacedArgumentMatcher(List<LocalizedMatcher> lastMatchers) {
-        throw new InvalidUseOfMatchersException(join(
-                "Misplaced argument matcher detected here:",
-                locationsOf(lastMatchers),
-                "",
-                "You cannot use argument matchers outside of verification or stubbing.",
-                "Examples of correct usage of argument matchers:",
-                "    when(mock.get(anyInt())).thenReturn(null);",
-                "    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());",
-                "    verify(mock).someMethod(contains(\"foo\"))",
-                "",
-                "Also, this error might show up because you use argument matchers with methods that cannot be mocked.",
-                "Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().",
-                MockitoLimitations.NON_PUBLIC_PARENT,
-                ""
-        ));
-    }
-
-    public void smartNullPointerException(String invocation, Location location) {
-        throw new SmartNullPointerException(join(
-                "You have a NullPointerException here:",
-                new LocationImpl(),
-                "because this method call was *not* stubbed correctly:",
-                location,
-                invocation,
-                ""
-        ));
-    }
-
-    public void noArgumentValueWasCaptured() {
-        throw new MockitoException(join(
-                "No argument value was captured!",
-                "You might have forgotten to use argument.capture() in verify()...",
-                "...or you used capture() in stubbing but stubbed method was not called.",
-                "Be aware that it is recommended to use capture() only with verify()",
-                "",
-                "Examples of correct argument capturing:",
-                "    ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);",
-                "    verify(mock).doSomething(argument.capture());",
-                "    assertEquals(\"John\", argument.getValue().getName());",
-                ""
-        ));
-    }
-
-    public void extraInterfacesDoesNotAcceptNullParameters() {
-        throw new MockitoException(join(
-                "extraInterfaces() does not accept null parameters."
-        ));
-    }
-
-    public void extraInterfacesAcceptsOnlyInterfaces(Class<?> wrongType) {
-        throw new MockitoException(join(
-                "extraInterfaces() accepts only interfaces.",
-                "You passed following type: " + wrongType.getSimpleName() + " which is not an interface."
-        ));
-    }
-
-    public void extraInterfacesCannotContainMockedType(Class<?> wrongType) {
-        throw new MockitoException(join(
-                "extraInterfaces() does not accept the same type as the mocked type.",
-                "You mocked following type: " + wrongType.getSimpleName(),
-                "and you passed the same very interface to the extraInterfaces()"
-        ));
-    }
-
-    public void extraInterfacesRequiresAtLeastOneInterface() {
-        throw new MockitoException(join(
-                "extraInterfaces() requires at least one interface."
-        ));
-    }
-
-    public void mockedTypeIsInconsistentWithSpiedInstanceType(Class<?> mockedType, Object spiedInstance) {
-        throw new MockitoException(join(
-                "Mocked type must be the same as the type of your spied instance.",
-                "Mocked type must be: " + spiedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
-                "  //correct spying:",
-                "  spy = mock( ->ArrayList.class<- , withSettings().spiedInstance( ->new ArrayList()<- );",
-                "  //incorrect - types don't match:",
-                "  spy = mock( ->List.class<- , withSettings().spiedInstance( ->new ArrayList()<- );"
-        ));
-    }
-
-    public void cannotCallAbstractRealMethod() {
-        throw new MockitoException(join(
-                "Cannot call abstract real method on java object!",
-                "Calling real methods is only possible when mocking non abstract method.",
-                "  //correct example:",
-                "  when(mockOfConcreteClass.nonAbstractMethod()).thenCallRealMethod();"
-        ));
-    }
-
-    public void cannotVerifyToString() {
-        throw new MockitoException(join(
-                "Mockito cannot verify toString()",
-                "toString() is too often used behind of scenes  (i.e. during String concatenation, in IDE debugging views). " +
-                        "Verifying it may give inconsistent or hard to understand results. " +
-                        "Not to mention that verifying toString() most likely hints awkward design (hard to explain in a short exception message. Trust me...)",
-                "However, it is possible to stub toString(). Stubbing toString() smells a bit funny but there are rare, legitimate use cases."
-        ));
-    }
-
-    public void moreThanOneAnnotationNotAllowed(String fieldName) {
-        throw new MockitoException("You cannot have more than one Mockito annotation on a field!\n" +
-                "The field '" + fieldName + "' has multiple Mockito annotations.\n" +
-                "For info how to use annotations see examples in javadoc for MockitoAnnotations class.");
-    }
-
-    public void unsupportedCombinationOfAnnotations(String undesiredAnnotationOne, String undesiredAnnotationTwo) {
-        throw new MockitoException("This combination of annotations is not permitted on a single field:\n" +
-                "@" + undesiredAnnotationOne + " and @" + undesiredAnnotationTwo);
-    }
-
-    public void cannotInitializeForSpyAnnotation(String fieldName, Exception details) {
-        throw new MockitoException(join("Cannot instantiate a @Spy for '" + fieldName + "' field.",
-                "You haven't provided the instance for spying at field declaration so I tried to construct the instance.",
-                "However, I failed because: " + details.getMessage(),
-                "Examples of correct usage of @Spy:",
-                "   @Spy List mock = new LinkedList();",
-                "   @Spy Foo foo; //only if Foo has parameterless constructor",
-                "   //also, don't forget about MockitoAnnotations.initMocks();",
-                ""), details);
-    }
-
-    public void cannotInitializeForInjectMocksAnnotation(String fieldName, Exception details) {
-        throw new MockitoException(join("Cannot instantiate @InjectMocks field named '" + fieldName + "'.",
-                "You haven't provided the instance at field declaration so I tried to construct the instance.",
-                "However, I failed because: " + details.getMessage(),
-                "Examples of correct usage of @InjectMocks:",
-                "   @InjectMocks Service service = new Service();",
-                "   @InjectMocks Service service;",
-                "   //also, don't forget about MockitoAnnotations.initMocks();",
-                "   //and... don't forget about some @Mocks for injection :)",
-                ""), details);
-    }
-
-    public void atMostAndNeverShouldNotBeUsedWithTimeout() {
-        throw new FriendlyReminderException(join("",
-                "Don't panic! I'm just a friendly reminder!",
-                "timeout() should not be used with atMost() or never() because...",
-                "...it does not make much sense - the test would have passed immediately in concurency",
-                "We kept this method only to avoid compilation errors when upgrading Mockito.",
-                "In future release we will remove timeout(x).atMost(y) from the API.",
-                "If you want to find out more please refer to issue 235",
-                ""));
-    }
-
-    public void fieldInitialisationThrewException(Field field, Throwable details) {
-        throw new MockitoException(join(
-                "Cannot instantiate @InjectMocks field named '" + field.getName() + "' of type '" + field.getType() +  "'.",
-                "You haven't provided the instance at field declaration so I tried to construct the instance.",
-                "However the constructor or the initialization block threw an exception : " + details.getMessage(),
-                ""), details);
-
-    }
-
-    public void invocationListenerDoesNotAcceptNullParameters() {
-        throw new MockitoException("invocationListeners() does not accept null parameters");
-    }
-
-    public void invocationListenersRequiresAtLeastOneListener() {
-        throw new MockitoException("invocationListeners() requires at least one listener");
-    }
-
-    public void invocationListenerThrewException(InvocationListener listener, Throwable listenerThrowable) {
-        throw new MockitoException(StringJoiner.join(
-                "The invocation listener with type " + listener.getClass().getName(),
-                "threw an exception : " + listenerThrowable.getClass().getName() + listenerThrowable.getMessage()), listenerThrowable);
-    }
-
-    public void cannotInjectDependency(Field field, Object matchingMock, Exception details) {
-        throw new MockitoException(join(
-                "Mockito couldn't inject mock dependency '" + new MockUtil().getMockName(matchingMock) + "' on field ",
-                "'" + field + "'",
-                "whose type '" + field.getDeclaringClass().getCanonicalName() + "' was annotated by @InjectMocks in your test.",
-                "Also I failed because: " + details.getCause().getMessage(),
-                ""
-        ), details);
-    }
-
-    public void mockedTypeIsInconsistentWithDelegatedInstanceType(Class mockedType, Object delegatedInstance) {
-        throw new MockitoException(join(
-                "Mocked type must be the same as the type of your delegated instance.",
-                "Mocked type must be: " + delegatedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
-                "  //correct delegate:",
-                "  spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new ArrayList()<- );",
-                "  //incorrect - types don't match:",
-                "  spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new HashSet()<- );"
-        ));
-    }
-
-    public void spyAndDelegateAreMutuallyExclusive() {
-        throw new MockitoException(join(
-                "Settings should not define a spy instance and a delegated instance at the same time."
-        )) ;
-    }
-
-    public void invalidArgumentRangeAtIdentityAnswerCreationTime() {
-        throw new MockitoException(join("Invalid argument index.",
-                "The index need to be a positive number that indicates the position of the argument to return.",
-                "However it is possible to use the -1 value to indicates that the last argument should be",
-                "returned."));
-    }
-
-    public int invalidArgumentPositionRangeAtInvocationTime(InvocationOnMock invocation, boolean willReturnLastParameter, int argumentIndex) {
-        throw new MockitoException(
-                join("Invalid argument index for the current invocation of method : ",
-                        " -> " + new MockUtil().getMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
-                        "",
-                        (willReturnLastParameter ?
-                                "Last parameter wanted" :
-                                "Wanted parameter at position " + argumentIndex) + " but " + possibleArgumentTypesOf(invocation),
-                        "The index need to be a positive number that indicates a valid position of the argument in the invocation.",
-                        "However it is possible to use the -1 value to indicates that the last argument should be returned.",
-                        ""));
-    }
-
-    private StringBuilder possibleArgumentTypesOf(InvocationOnMock invocation) {
-        Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
-        if (parameterTypes.length == 0) {
-            return new StringBuilder("the method has no arguments.\n");
-        }
-
-        StringBuilder stringBuilder = new StringBuilder("the possible argument indexes for this method are :\n");
-        for (int i = 0, parameterTypesLength = parameterTypes.length; i < parameterTypesLength; i++) {
-            stringBuilder.append("    [").append(i);
-
-            if (invocation.getMethod().isVarArgs() && i == parameterTypesLength - 1) {
-                stringBuilder.append("+] ").append(parameterTypes[i].getComponentType().getSimpleName()).append("  <- Vararg").append("\n");
-            } else {
-                stringBuilder.append("] ").append(parameterTypes[i].getSimpleName()).append("\n");
-            }
-        }
-        return stringBuilder;
-    }
-
-    public void wrongTypeOfArgumentToReturn(InvocationOnMock invocation, String expectedType, Class actualType, int argumentIndex) {
-        throw new WrongTypeOfReturnValue(join(
-                "The argument of type '" + actualType.getSimpleName() + "' cannot be returned because the following ",
-                "method should return the type '" + expectedType + "'",
-                " -> " + new MockUtil().getMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
-                "",
-                "The reason for this error can be :",
-                "1. The wanted argument position is incorrect.",
-                "2. The answer is used on the wrong interaction.",
-                "",
-                "Position of the wanted argument is " + argumentIndex + " and " + possibleArgumentTypesOf(invocation),
-                "***",
-                "However if you're still unsure why you're getting above error read on.",
-                "Due to the nature of the syntax above problem might occur because:",
-                "1. This exception *might* occur in wrongly written multi-threaded tests.",
-                "   Please refer to Mockito FAQ on limitations of concurrency testing.",
-                "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
-                "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
-                ""
-        ));
-    }
-
-    public void defaultAnswerDoesNotAcceptNullParameter() {
-        throw new MockitoException("defaultAnswer() does not accept null parameter");
-    }
-
-    public void serializableWontWorkForObjectsThatDontImplementSerializable(Class classToMock) {
-        throw new MockitoException(join(
-                "You are using the setting 'withSettings().serializable()' however the type you are trying to mock '" + classToMock.getSimpleName() + "'",
-                "do not implement Serializable AND do not have a no-arg constructor.",
-                "This combination is requested, otherwise you will get an 'java.io.InvalidClassException' when the mock will be serialized",
-                "",
-                "Also note that as requested by the Java serialization specification, the whole hierarchy need to implements Serializable,",
-                "i.e. the top-most superclass has to implements Serializable.",
-                ""
-        ));
-    }
-    
-    public void delegatedMethodHasWrongReturnType(Method mockMethod, Method delegateMethod, Object mock, Object delegate) {
-    	throw new MockitoException(join(
-    	        "Methods called on delegated instance must have compatible return types with the mock.",
-    	        "When calling: " + mockMethod + " on mock: " + new MockUtil().getMockName(mock),
-    	        "return type should be: " + mockMethod.getReturnType().getSimpleName() + ", but was: " + delegateMethod.getReturnType().getSimpleName(),
-    	        "Check that the instance passed to delegatesTo() is of the correct type or contains compatible methods",
-    	        "(delegate instance had type: " + delegate.getClass().getSimpleName() + ")"
-    	));
-    }
-
-	public void delegatedMethodDoesNotExistOnDelegate(Method mockMethod, Object mock, Object delegate) {
-		throw new MockitoException(join(
-    	        "Methods called on mock must exist in delegated instance.",
-    	        "When calling: " + mockMethod + " on mock: " + new MockUtil().getMockName(mock),
-    	        "no such method was found.",
-    	        "Check that the instance passed to delegatesTo() is of the correct type or contains compatible methods",
-    	        "(delegate instance had type: " + delegate.getClass().getSimpleName() + ")"
-    	));
-	}
-
-    public void usingConstructorWithFancySerializable(SerializableMode mode) {
-        throw new MockitoException("Mocks instantiated with constructor cannot be combined with " + mode + " serialization mode.");
-    }
-}
diff --git a/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java b/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java
index 4da7998..491ff40 100644
--- a/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java
+++ b/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java
@@ -7,8 +7,20 @@
 
 import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
 
-
-
+/**
+ * Base class for verification errors emitted by Mockito.
+ * Verification errors are triggered by "verify" methods,
+ * for example {@link org.mockito.Mockito#verify(Object)} or {@link org.mockito.Mockito#verifyNoMoreInteractions(Object...)}.
+ * All error classes that inherit from this class will have the stack trace filtered.
+ * Filtering removes Mockito internal stack trace elements to provide clean stack traces and improve productivity.
+ * <p>
+ * The stack trace is filtered from mockito calls if you are using {@link #getStackTrace()}.
+ * For debugging purpose though you can still access the full stacktrace using {@link #getUnfilteredStackTrace()}.
+ * However note that other calls related to the stackTrace will refer to the filter stacktrace.
+ * <p>
+ * Advanced users and framework integrators can control stack trace filtering behavior
+ * via {@link org.mockito.plugins.StackTraceCleanerProvider} classpath plugin.
+ */
 public class MockitoAssertionError extends AssertionError {
 
     private static final long serialVersionUID = 1L;
@@ -18,12 +30,24 @@
         super(message);
 
         unfilteredStackTrace = getStackTrace();
-        
+
         ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
         filter.filter(this);
     }
 
+    /**
+     * Creates a copy of the given assertion error with the custom failure message prepended.
+     * @param error The assertion error to copy
+     * @param message The custom message to prepend
+     * @since 2.1.0
+     */
+    public MockitoAssertionError(MockitoAssertionError error, String message) {
+        super(message + "\n" + error.getMessage());
+        super.setStackTrace(error.getStackTrace());
+        unfilteredStackTrace = error.getUnfilteredStackTrace();
+    }
+
     public StackTraceElement[] getUnfilteredStackTrace() {
         return unfilteredStackTrace;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/base/MockitoException.java b/src/main/java/org/mockito/exceptions/base/MockitoException.java
index 3aa4362..d774702 100644
--- a/src/main/java/org/mockito/exceptions/base/MockitoException.java
+++ b/src/main/java/org/mockito/exceptions/base/MockitoException.java
@@ -10,13 +10,15 @@
 
 /**
  * Raised by mockito to emit an error either due to Mockito, or due to the User.
- *
+ * All exception classes that inherit from this class will have the stack trace filtered.
+ * Filtering removes Mockito internal stack trace elements to provide clean stack traces and improve productivity.
  * <p>
- *     The stack trace is filtered from mockito calls if you are using {@link #getStackTrace()}.
- *     For debugging purpose though you can still access the full stacktrace using {@link #getUnfilteredStackTrace()}.
- *     However note that other calls related to the stackTrace will refer to the filter stacktrace.
- * </p>
- *
+ * The stack trace is filtered from mockito calls if you are using {@link #getStackTrace()}.
+ * For debugging purpose though you can still access the full stacktrace using {@link #getUnfilteredStackTrace()}.
+ * However note that other calls related to the stackTrace will refer to the filter stacktrace.
+ * <p>
+ * Advanced users and framework integrators can control stack trace filtering behavior
+ * via {@link org.mockito.plugins.StackTraceCleanerProvider} classpath plugin.
  */
 public class MockitoException extends RuntimeException {
 
@@ -37,7 +39,7 @@
 
     private void filterStackTrace() {
         unfilteredStackTrace = getStackTrace();
-        
+
         ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
         filter.filter(this);
     }
diff --git a/src/main/java/org/mockito/exceptions/base/MockitoInitializationException.java b/src/main/java/org/mockito/exceptions/base/MockitoInitializationException.java
new file mode 100644
index 0000000..019fe0b
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/base/MockitoInitializationException.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+public class MockitoInitializationException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public MockitoInitializationException(String message) {
+        super(message);
+    }
+
+    public MockitoInitializationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/base/MockitoSerializationIssue.java b/src/main/java/org/mockito/exceptions/base/MockitoSerializationIssue.java
index 67a7387..458b56d 100644
--- a/src/main/java/org/mockito/exceptions/base/MockitoSerializationIssue.java
+++ b/src/main/java/org/mockito/exceptions/base/MockitoSerializationIssue.java
@@ -30,12 +30,6 @@
         filterStackTrace();
     }
 
-    @Override
-    public StackTraceElement[] getStackTrace() {
-        filterStackTrace();
-        return super.getStackTrace();
-    }
-
     private void filterStackTrace() {
         unfilteredStackTrace = super.getStackTrace();
 
diff --git a/src/main/java/org/mockito/exceptions/base/package-info.java b/src/main/java/org/mockito/exceptions/base/package-info.java
new file mode 100644
index 0000000..088b380
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/base/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Base classes for exceptions and errors, stack trace filtering/removing logic.
+ */
+package org.mockito.exceptions.base;
diff --git a/src/main/java/org/mockito/exceptions/base/package.html b/src/main/java/org/mockito/exceptions/base/package.html
deleted file mode 100644
index 4f07e45..0000000
--- a/src/main/java/org/mockito/exceptions/base/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Base classes for exceptions and errors, stack trace filtering/removing logic.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/misusing/CannotStubVoidMethodWithReturnValue.java b/src/main/java/org/mockito/exceptions/misusing/CannotStubVoidMethodWithReturnValue.java
index 710f1e1..32b73a1 100644
--- a/src/main/java/org/mockito/exceptions/misusing/CannotStubVoidMethodWithReturnValue.java
+++ b/src/main/java/org/mockito/exceptions/misusing/CannotStubVoidMethodWithReturnValue.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.exceptions.misusing;
 
 import org.mockito.exceptions.base.MockitoException;
diff --git a/src/main/java/org/mockito/exceptions/misusing/FriendlyReminderException.java b/src/main/java/org/mockito/exceptions/misusing/FriendlyReminderException.java
index 1201890..57d8015 100644
--- a/src/main/java/org/mockito/exceptions/misusing/FriendlyReminderException.java
+++ b/src/main/java/org/mockito/exceptions/misusing/FriendlyReminderException.java
@@ -14,4 +14,4 @@
     public FriendlyReminderException(String message) {
         super(message);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java b/src/main/java/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java
index 64623a3..a6a17ee 100644
--- a/src/main/java/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java
+++ b/src/main/java/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java
@@ -18,4 +18,4 @@
     public InvalidUseOfMatchersException() {
         super("");
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/MockitoConfigurationException.java b/src/main/java/org/mockito/exceptions/misusing/MockitoConfigurationException.java
index ae39427..89e6632 100644
--- a/src/main/java/org/mockito/exceptions/misusing/MockitoConfigurationException.java
+++ b/src/main/java/org/mockito/exceptions/misusing/MockitoConfigurationException.java
@@ -2,19 +2,19 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.exceptions.misusing;

-

-import org.mockito.exceptions.base.MockitoException;

-

-public class MockitoConfigurationException extends MockitoException {

-

-    private static final long serialVersionUID = 1L;

-

-    public MockitoConfigurationException(String message) {

-        super(message);

-    }

-

-    public MockitoConfigurationException(String message, Exception cause) {

-        super(message, cause);

-    }

-}
\ No newline at end of file
+package org.mockito.exceptions.misusing;
+
+import org.mockito.exceptions.base.MockitoException;
+
+public class MockitoConfigurationException extends MockitoException {
+
+    private static final long serialVersionUID = 1L;
+
+    public MockitoConfigurationException(String message) {
+        super(message);
+    }
+
+    public MockitoConfigurationException(String message, Exception cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/PotentialStubbingProblem.java b/src/main/java/org/mockito/exceptions/misusing/PotentialStubbingProblem.java
new file mode 100644
index 0000000..668adfd
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/misusing/PotentialStubbingProblem.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.exceptions.misusing;
+
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.junit.MockitoRule;
+
+/**
+ * {@code PotentialStubbingProblem} improves productivity by failing the test early when the user
+ * misconfigures mock's stubbing.
+ * <p>
+ * {@code PotentialStubbingProblem} exception is a part of "strict stubbing" Mockito API
+ * intended to drive cleaner tests and better productivity with Mockito mocks.
+ * For more information see {@link Strictness}.
+ * <p>
+ * {@code PotentialStubbingProblem} is thrown when mocked method is stubbed with some argument in test
+ * but then invoked with <strong>different</strong> argument in the code.
+ * This scenario is called "stubbing argument mismatch".
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * //test method:
+ * given(mock.getSomething(100)).willReturn(something);
+ *
+ * //code under test:
+ * Something something = mock.getSomething(50); // <-- stubbing argument mismatch
+ * </code></pre>
+ * The stubbing argument mismatch typically indicates:
+ * <ol>
+ *     <li>Mistake, typo or misunderstanding in the test code, the argument(s) used when declaring stubbing are different by mistake</li>
+ *     <li>Mistake, typo or misunderstanding in the code under test, the argument(s) used when invoking stubbed method are different by mistake</li>
+ *     <li>Intentional use of stubbed method with different argument, either in the test (more stubbing) or in code under test</li>
+ * </ol>
+ * User mistake (use case 1 and 2) make up 95% of the stubbing argument mismatch cases.
+ * {@code PotentialStubbingProblem} improves productivity in those scenarios
+ * by failing early with clean message pointing out the incorrect stubbing or incorrect invocation of stubbed method.
+ * In remaining 5% of the cases (use case 3) {@code PotentialStubbingProblem} can give false negative signal
+ * indicating non-existing problem. The exception message contains information how to opt-out from the feature.
+ * Mockito optimizes for enhanced productivity of 95% of the cases while offering opt-out for remaining 5%.
+ * False negative signal for edge cases is a trade-off for general improvement of productivity.
+ * <p>
+ * What to do if you fall into use case 3 (false negative signal)? You have 2 options:
+ * <ol>
+ *  <li>Do you see this exception because you're stubbing the same method multiple times in the same test?
+ *  In that case, please use {@link org.mockito.BDDMockito#willReturn(Object)} or {@link Mockito#doReturn(Object)}
+ *  family of methods for stubbing.
+ *  Convenient stubbing via {@link Mockito#when(Object)} has its drawbacks: the framework cannot distinguish between
+ *  actual invocation on mock (real code) and the stubbing declaration (test code).
+ *  Hence the need to use {@link org.mockito.BDDMockito#willReturn(Object)} or {@link Mockito#doReturn(Object)} for certain edge cases.
+ *  It is a well known limitation of Mockito API and another example how Mockito optimizes its clean API for 95% of the cases
+ *  while still supporting edge cases.
+ *  </li>
+ *  <li>Reduce the strictness level in the test method (only for JUnit Rules):
+ * <pre class="code"><code class="java">
+ * public class ExampleTest {
+ *     &#064;Rule
+ *     public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+ *
+ *     &#064;Test public void exampleTest() {
+ *         //Change the strictness level only for this test method:
+ *         mockito.strictness(Strictness.LENIENT);
+ *
+ *         //remaining test code
+ *     }
+ * }
+ * </code></pre>
+ *  Currently, reducing strictness is only available to JUnit rules.
+ *  If you need it in a different context let us know at <a href="https://github.com/mockito/mockito/issues/857">issue 857</a>.
+ *  </li>
+ *  <li>To opt-out in Mockito 2.x, simply remove the strict stubbing setting in the test class.</li>
+ * </ol>
+ * <p>
+ * Mockito team is very eager to hear feedback about "strict stubbing" feature, let us know by commenting on GitHub
+ * <a href="https://github.com/mockito/mockito/issues/769">issue 769</a>.
+ * Strict stubbing is an attempt to improve testability and productivity with Mockito. Tell us what you think!
+ *
+ * @since 2.3.0
+ */
+public class PotentialStubbingProblem extends MockitoException {
+    public PotentialStubbingProblem(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/RedundantListenerException.java b/src/main/java/org/mockito/exceptions/misusing/RedundantListenerException.java
new file mode 100644
index 0000000..98fb07d
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/misusing/RedundantListenerException.java
@@ -0,0 +1,21 @@
+package org.mockito.exceptions.misusing;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.listeners.MockitoListener;
+
+/**
+ * Reported when instance of {@link org.mockito.listeners.MockitoListener}
+ * is being added to Mockito (see {@link org.mockito.MockitoFramework})
+ * and there is already a listener with this implementation type registered.
+ * Note that it is ok to add multiple <strong>different</strong> implementations of the same listener interface type.
+ * <p>
+ * Indicates a user error - previous listener was not removed
+ * according to the API specification - see {@link org.mockito.MockitoFramework#addListener(MockitoListener)}.
+ *
+ * @since 2.5.2
+ */
+public class RedundantListenerException extends MockitoException {
+    public RedundantListenerException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/UnfinishedMockingSessionException.java b/src/main/java/org/mockito/exceptions/misusing/UnfinishedMockingSessionException.java
new file mode 100644
index 0000000..be38d05
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/misusing/UnfinishedMockingSessionException.java
@@ -0,0 +1,21 @@
+package org.mockito.exceptions.misusing;
+
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.session.MockitoSessionBuilder;
+
+/**
+ * This exception prevents the user from forgetting to use {@link MockitoSession#finishMocking()}.
+ * When {@link MockitoSession} is started is used
+ * it needs to be concluded with {@link MockitoSession#finishMocking()}.
+ * <p>
+ * For details on mocking session lifecycle see {@link MockitoSessionBuilder#startMocking()}
+ * and {@link MockitoSession#finishMocking()}. For examples of use see {@link MockitoSession}.
+ *
+ * @since 2.7.0
+ */
+public class UnfinishedMockingSessionException extends MockitoException {
+    public UnfinishedMockingSessionException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/UnfinishedVerificationException.java b/src/main/java/org/mockito/exceptions/misusing/UnfinishedVerificationException.java
index 3d06840..323c1f6 100644
--- a/src/main/java/org/mockito/exceptions/misusing/UnfinishedVerificationException.java
+++ b/src/main/java/org/mockito/exceptions/misusing/UnfinishedVerificationException.java
@@ -8,7 +8,7 @@
 import org.mockito.exceptions.base.MockitoException;
 
 public class UnfinishedVerificationException extends MockitoException {
-    
+
     private static final long serialVersionUID = 1L;
 
     public UnfinishedVerificationException(String message) {
diff --git a/src/main/java/org/mockito/exceptions/misusing/UnnecessaryStubbingException.java b/src/main/java/org/mockito/exceptions/misusing/UnnecessaryStubbingException.java
new file mode 100644
index 0000000..c8713b3
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/misusing/UnnecessaryStubbingException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.exceptions.misusing;
+
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.MockitoHint;
+import org.mockito.quality.Strictness;
+
+/**
+ * This exception indicates presence of unused stubbings.
+ * It is highly recommended to remove unused stubbings to keep the codebase clean.
+ * You can opt-out from detecting unused stubbings by configuring:
+ * <ul>
+ *     <li>JUnit rule - {@link MockitoRule#strictness(Strictness)} or {@link MockitoRule#silent()}</li>
+ *     <li>JUnit runner - {@link MockitoJUnitRunner.Silent}</li>
+ *     <li>Mockito session - {@link MockitoSession}</li>
+ * </ul>
+ * For more information about detecting unused stubbings, see {@link MockitoHint}.
+ * <p>
+ * Unnecessary stubbings are stubbed method calls that were never realized during test execution. Example:
+ * <pre class="code"><code class="java">
+ * //code under test:
+ * ...
+ * String result = translator.translate("one")
+ * ...
+ *
+ * //test:
+ * ...
+ * when(translator.translate("one")).thenReturn("jeden"); // <- stubbing realized during code execution
+ * when(translator.translate("two")).thenReturn("dwa"); // <- stubbing never realized
+ * ...
+ * </pre>
+ * Notice that one of the stubbed methods were never realized in the code under test, during test execution.
+ * The stray stubbing might be an oversight of the developer, the artifact of copy-paste
+ * or the effect not understanding the test/code.
+ * Either way, the developer ends up with unnecessary test code.
+ * In order to keep the codebase clean & maintainable it is necessary to remove unnecessary code.
+ * Otherwise tests are harder to read and reason about.
+ * <p>
+ * Mockito JUnit Runner triggers <code>UnnecessaryStubbingException</code> only when none of the test methods use the stubbings.
+ * This means that it is ok to put default stubbing in a 'setup' method or in test class constructor.
+ * That default stubbing needs to be used at least once by one of the test methods.
+ * <p>
+ * To find out more about detecting unused stubbings see {@link MockitoHint}.
+ * See javadoc for {@link MockitoRule} to understand the behavior or Mockito JUnit Rules.
+ * See javadoc for {@link MockitoJUnitRunner} to find out how Mockito JUnit Runner detects unused stubs.
+ * See javadoc for {@link MockitoSession} to find out about detecting unused stubs without JUnit.
+ */
+public class UnnecessaryStubbingException extends MockitoException {
+    public UnnecessaryStubbingException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java b/src/main/java/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java
index 46acc77..5fa2e29 100644
--- a/src/main/java/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java
+++ b/src/main/java/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java
@@ -2,15 +2,15 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.exceptions.misusing;

-

-import org.mockito.exceptions.base.MockitoException;

-

-public class WrongTypeOfReturnValue extends MockitoException {

-

-    private static final long serialVersionUID = 1L;

-

-    public WrongTypeOfReturnValue(String message) {

-        super(message);

-    }

-}

+package org.mockito.exceptions.misusing;
+
+import org.mockito.exceptions.base.MockitoException;
+
+public class WrongTypeOfReturnValue extends MockitoException {
+
+    private static final long serialVersionUID = 1L;
+
+    public WrongTypeOfReturnValue(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/misusing/package-info.java b/src/main/java/org/mockito/exceptions/misusing/package-info.java
new file mode 100644
index 0000000..60bed8a
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/misusing/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Exceptions thrown when Mockito is misused.
+ */
+package org.mockito.exceptions.misusing;
diff --git a/src/main/java/org/mockito/exceptions/misusing/package.html b/src/main/java/org/mockito/exceptions/misusing/package.html
deleted file mode 100644
index 64bfbc5..0000000
--- a/src/main/java/org/mockito/exceptions/misusing/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Exceptions thrown when Mockito is misused.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/package-info.java b/src/main/java/org/mockito/exceptions/package-info.java
new file mode 100644
index 0000000..e2dbb95
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito configuration utilities
+ */
+package org.mockito.exceptions;
diff --git a/src/main/java/org/mockito/exceptions/package.html b/src/main/java/org/mockito/exceptions/package.html
deleted file mode 100644
index a2e03c3..0000000
--- a/src/main/java/org/mockito/exceptions/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Exception messages, exception hierarchies.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/stacktrace/StackTraceCleaner.java b/src/main/java/org/mockito/exceptions/stacktrace/StackTraceCleaner.java
index abd1a32..a3229a8 100644
--- a/src/main/java/org/mockito/exceptions/stacktrace/StackTraceCleaner.java
+++ b/src/main/java/org/mockito/exceptions/stacktrace/StackTraceCleaner.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.exceptions.stacktrace;
 
 /**
@@ -5,22 +9,20 @@
  * Mockito stack trace filtering mechanism uses this information.
  * <p>
  * Excluding an element will make it not show in the cleaned stack trace.
- * Not-excluding an element does not guarantee it will be shown
- * (e.g. it depends on the implementation of
- * Mockito internal {@link org.mockito.internal.exceptions.stacktrace.StackTraceFilter}).
+ * Not-excluding an element does not guarantee it will be shown (e.g. it depends on the implementation of
+ * {@linkplain org.mockito.internal.exceptions.stacktrace.StackTraceFilter Mockito internal cleaner}).
  * <p>
- * The implementations are required to be thread safe. For example, make them stateless.
+ * The implementations are required to be thread safe ; for example, make them stateless.
  * <p>
- * See the default implementation: {@link org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleaner}.
- *
+ * See also the {@linkplain org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleaner Mockito default implementation}
  */
 public interface StackTraceCleaner {
 
     /**
-     * Decides if element is excluded.
+     * Decides if element is included.
      *
      * @param candidate element of the actual stack trace
      * @return whether the element should be excluded from cleaned stack trace.
      */
-    boolean isOut(StackTraceElement candidate);
+    boolean isIn(StackTraceElement candidate);
 }
diff --git a/src/main/java/org/mockito/exceptions/stacktrace/package-info.java b/src/main/java/org/mockito/exceptions/stacktrace/package-info.java
new file mode 100644
index 0000000..39f8bdf
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/stacktrace/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Stack trace filtering / cleaning public APIs.
+ */
+package org.mockito.exceptions.stacktrace;
diff --git a/src/main/java/org/mockito/exceptions/stacktrace/package.html b/src/main/java/org/mockito/exceptions/stacktrace/package.html
deleted file mode 100644
index 2251473..0000000
--- a/src/main/java/org/mockito/exceptions/stacktrace/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Stack trace filtering / cleaning public APIs.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/verification/ArgumentsAreDifferent.java b/src/main/java/org/mockito/exceptions/verification/ArgumentsAreDifferent.java
index 41d01bb..a44cc6f 100644
--- a/src/main/java/org/mockito/exceptions/verification/ArgumentsAreDifferent.java
+++ b/src/main/java/org/mockito/exceptions/verification/ArgumentsAreDifferent.java
@@ -5,8 +5,9 @@
 
 package org.mockito.exceptions.verification;
 
+import static org.mockito.internal.util.StringUtil.removeFirstLine;
+
 import org.mockito.exceptions.base.MockitoAssertionError;
-import org.mockito.internal.util.RemoveFirstLine;
 
 public class ArgumentsAreDifferent extends MockitoAssertionError {
 
@@ -15,9 +16,9 @@
     public ArgumentsAreDifferent(String message) {
         super(message);
     }
-    
+
     @Override
     public String toString() {
-        return new RemoveFirstLine().of(super.toString());
+        return removeFirstLine(super.toString());
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/verification/NoInteractionsWanted.java b/src/main/java/org/mockito/exceptions/verification/NoInteractionsWanted.java
index e1aafb5..9dccf3b 100644
--- a/src/main/java/org/mockito/exceptions/verification/NoInteractionsWanted.java
+++ b/src/main/java/org/mockito/exceptions/verification/NoInteractionsWanted.java
@@ -17,4 +17,4 @@
     public NoInteractionsWanted(String message) {
         super(message);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/verification/SmartNullPointerException.java b/src/main/java/org/mockito/exceptions/verification/SmartNullPointerException.java
index c1f7f0f..83f2aab 100644
--- a/src/main/java/org/mockito/exceptions/verification/SmartNullPointerException.java
+++ b/src/main/java/org/mockito/exceptions/verification/SmartNullPointerException.java
@@ -2,15 +2,15 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.exceptions.verification;

-

-import org.mockito.exceptions.base.MockitoException;

-

-public class SmartNullPointerException extends MockitoException {

-

-    private static final long serialVersionUID = 1L;

-

-    public SmartNullPointerException(String message) {

-        super(message);

-    }

-}
\ No newline at end of file
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoException;
+
+public class SmartNullPointerException extends MockitoException {
+
+    private static final long serialVersionUID = 1L;
+
+    public SmartNullPointerException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/mockito/exceptions/verification/TooLittleActualInvocations.java b/src/main/java/org/mockito/exceptions/verification/TooLittleActualInvocations.java
index 01af460..d47a440 100644
--- a/src/main/java/org/mockito/exceptions/verification/TooLittleActualInvocations.java
+++ b/src/main/java/org/mockito/exceptions/verification/TooLittleActualInvocations.java
@@ -10,7 +10,7 @@
 public class TooLittleActualInvocations extends MockitoAssertionError {
 
     private static final long serialVersionUID = 1L;
-    
+
     public TooLittleActualInvocations(String message) {
         super(message);
     }
diff --git a/src/main/java/org/mockito/exceptions/verification/WantedButNotInvoked.java b/src/main/java/org/mockito/exceptions/verification/WantedButNotInvoked.java
index 007d70c..e791d56 100644
--- a/src/main/java/org/mockito/exceptions/verification/WantedButNotInvoked.java
+++ b/src/main/java/org/mockito/exceptions/verification/WantedButNotInvoked.java
@@ -5,8 +5,9 @@
 
 package org.mockito.exceptions.verification;
 
+import static org.mockito.internal.util.StringUtil.removeFirstLine;
+
 import org.mockito.exceptions.base.MockitoAssertionError;
-import org.mockito.internal.util.RemoveFirstLine;
 
 public class WantedButNotInvoked extends MockitoAssertionError {
 
@@ -15,9 +16,9 @@
     public WantedButNotInvoked(String message) {
         super(message);
     }
-    
+
     @Override
     public String toString() {
-        return new RemoveFirstLine().of(super.toString());
+        return removeFirstLine(super.toString());
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java b/src/main/java/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java
index cf1321f..32bf882 100644
--- a/src/main/java/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java
+++ b/src/main/java/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java
@@ -5,13 +5,14 @@
 
 package org.mockito.exceptions.verification.junit;
 
+import static org.mockito.internal.util.StringUtil.removeFirstLine;
+
 import junit.framework.ComparisonFailure;
 import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
-import org.mockito.internal.util.RemoveFirstLine;
 
 
 public class ArgumentsAreDifferent extends ComparisonFailure {
-    
+
     private static final long serialVersionUID = 1L;
     private final String message;
     private final StackTraceElement[] unfilteredStackTrace;
@@ -19,23 +20,23 @@
     public ArgumentsAreDifferent(String message, String wanted, String actual) {
         super(message, wanted, actual);
         this.message = message;
-        
+
         unfilteredStackTrace = getStackTrace();
         ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
         filter.filter(this);
     }
-    
+
     @Override
     public String getMessage() {
         return message;
     }
-    
+
     public StackTraceElement[] getUnfilteredStackTrace() {
         return unfilteredStackTrace;
     }
-    
+
     @Override
     public String toString() {
-        return new RemoveFirstLine().of(super.toString());
+        return removeFirstLine(super.toString());
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/exceptions/verification/junit/JUnitTool.java b/src/main/java/org/mockito/exceptions/verification/junit/JUnitTool.java
deleted file mode 100644
index 70af301..0000000
--- a/src/main/java/org/mockito/exceptions/verification/junit/JUnitTool.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.exceptions.verification.junit;

-

-@Deprecated

-/**

- * @Deprecated. This class has been moved to internal packages because it was never meant to be public.

- * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.junit.JUnitTool}.

- * However, the package clearly states that the class in a part of a public API so it can change.

- */

-public class JUnitTool {

-    

-    public static boolean hasJUnit() {

-        return org.mockito.internal.junit.JUnitTool.hasJUnit();

-    }

-

-    public static AssertionError createArgumentsAreDifferentException(String message, String wanted, String actual)  {

-        return org.mockito.internal.junit.JUnitTool.createArgumentsAreDifferentException(message, wanted, actual);

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/verification/junit/package-info.java b/src/main/java/org/mockito/exceptions/verification/junit/package-info.java
new file mode 100644
index 0000000..4542d34
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/verification/junit/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * JUnit integration to provide better support for junit runners in IDEs.
+ */
+package org.mockito.exceptions.verification.junit;
diff --git a/src/main/java/org/mockito/exceptions/verification/junit/package.html b/src/main/java/org/mockito/exceptions/verification/junit/package.html
deleted file mode 100644
index 4b1a32e..0000000
--- a/src/main/java/org/mockito/exceptions/verification/junit/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-JUnit integration to provide better support for junit runners in IDEs. 
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/exceptions/verification/package-info.java b/src/main/java/org/mockito/exceptions/verification/package-info.java
new file mode 100644
index 0000000..ae3d3d6
--- /dev/null
+++ b/src/main/java/org/mockito/exceptions/verification/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Verification errors.
+ */
+package org.mockito.exceptions.verification;
diff --git a/src/main/java/org/mockito/exceptions/verification/package.html b/src/main/java/org/mockito/exceptions/verification/package.html
deleted file mode 100644
index 6471a75..0000000
--- a/src/main/java/org/mockito/exceptions/verification/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Verification errors.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/hamcrest/MockitoHamcrest.java b/src/main/java/org/mockito/hamcrest/MockitoHamcrest.java
index f6ccd03..5f55d22 100644
--- a/src/main/java/org/mockito/hamcrest/MockitoHamcrest.java
+++ b/src/main/java/org/mockito/hamcrest/MockitoHamcrest.java
@@ -6,12 +6,14 @@
 
 import org.hamcrest.Matcher;
 import org.mockito.ArgumentMatcher;
-import org.mockito.Mockito;
+import org.mockito.internal.hamcrest.HamcrestArgumentMatcher;
+
+import static org.mockito.internal.hamcrest.MatcherGenericTypeExtractor.genericTypeOfMatcher;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+import static org.mockito.internal.util.Primitives.defaultValue;
 
 /**
- * Allows matching arguments with hamcrest matchers; back ported from 2.7.13
- * to help with upgrade.
- * 
+ * Allows matching arguments with hamcrest matchers.
  * <b>Requires</b> <a href="http://hamcrest.org/JavaHamcrest/">hamcrest</a> on classpath,
  * Mockito <b>does not</b> depend on hamcrest!
  * Note the <b>NullPointerException</b> auto-unboxing caveat described below.
@@ -56,7 +58,8 @@
      */
     @SuppressWarnings("unchecked")
     public static <T> T argThat(Matcher<T> matcher) {
-        return Mockito.argThat(matcher);
+        reportMatcher(matcher);
+        return  (T) defaultValue(genericTypeOfMatcher(matcher.getClass()));
     }
 
     /**
@@ -69,7 +72,8 @@
      * @return <code>0</code>.
      */
     public static char charThat(Matcher<Character> matcher) {
-        return Mockito.charThat(matcher);
+        reportMatcher(matcher);
+        return 0;
     }
 
     /**
@@ -82,7 +86,8 @@
      * @return <code>false</code>.
      */
     public static boolean booleanThat(Matcher<Boolean> matcher) {
-        return Mockito.booleanThat(matcher);
+        reportMatcher(matcher);
+        return false;
     }
 
     /**
@@ -95,7 +100,8 @@
      * @return <code>0</code>.
      */
     public static byte byteThat(Matcher<Byte> matcher) {
-        return Mockito.byteThat(matcher);
+        reportMatcher(matcher);
+        return 0;
     }
 
     /**
@@ -108,7 +114,8 @@
      * @return <code>0</code>.
      */
     public static short shortThat(Matcher<Short> matcher) {
-        return Mockito.shortThat(matcher);
+        reportMatcher(matcher);
+        return 0;
     }
 
     /**
@@ -121,7 +128,8 @@
      * @return <code>0</code>.
      */
     public static int intThat(Matcher<Integer> matcher) {
-        return Mockito.intThat(matcher);
+        reportMatcher(matcher);
+        return 0;
     }
 
     /**
@@ -134,7 +142,8 @@
      * @return <code>0</code>.
      */
     public static long longThat(Matcher<Long> matcher) {
-        return Mockito.longThat(matcher);
+        reportMatcher(matcher);
+        return 0;
     }
 
     /**
@@ -147,7 +156,8 @@
      * @return <code>0</code>.
      */
     public static float floatThat(Matcher<Float> matcher) {
-        return Mockito.floatThat(matcher);
+        reportMatcher(matcher);
+        return 0;
     }
 
     /**
@@ -160,6 +170,11 @@
      * @return <code>0</code>.
      */
     public static double doubleThat(Matcher<Double> matcher) {
-        return Mockito.doubleThat(matcher);
+        reportMatcher(matcher);
+        return 0;
+    }
+
+    private static <T> void reportMatcher(Matcher<T> matcher) {
+        mockingProgress().getArgumentMatcherStorage().reportMatcher(new HamcrestArgumentMatcher<T>(matcher));
     }
 }
diff --git a/src/main/java/org/mockito/hamcrest/package-info.java b/src/main/java/org/mockito/hamcrest/package-info.java
new file mode 100644
index 0000000..3e68039
--- /dev/null
+++ b/src/main/java/org/mockito/hamcrest/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito Hamcrest matcher integration.
+ */
+package org.mockito.hamcrest;
diff --git a/src/main/java/org/mockito/internal/InOrderImpl.java b/src/main/java/org/mockito/internal/InOrderImpl.java
index 0a2808f..0d67ae7 100644
--- a/src/main/java/org/mockito/internal/InOrderImpl.java
+++ b/src/main/java/org/mockito/internal/InOrderImpl.java
@@ -5,11 +5,7 @@
 
 package org.mockito.internal;
 
-import java.util.LinkedList;
-import java.util.List;
-
 import org.mockito.InOrder;
-import org.mockito.exceptions.Reporter;
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.internal.verification.InOrderContextImpl;
 import org.mockito.internal.verification.InOrderWrapper;
@@ -18,33 +14,42 @@
 import org.mockito.internal.verification.api.VerificationInOrderMode;
 import org.mockito.invocation.Invocation;
 import org.mockito.verification.VerificationMode;
+import org.mockito.internal.verification.VerificationWrapper;
+import org.mockito.internal.verification.VerificationWrapperInOrderWrapper;
+
+import static org.mockito.internal.exceptions.Reporter.inOrderRequiresFamiliarMock;
+
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Allows verifying in order. This class should not be exposed, hence default access.
  */
 public class InOrderImpl implements InOrder, InOrderContext {
-    
+
     private final MockitoCore mockitoCore = new MockitoCore();
-    private final Reporter reporter = new Reporter();
     private final List<Object> mocksToBeVerifiedInOrder = new LinkedList<Object>();
     private final InOrderContext inOrderContext = new InOrderContextImpl();
-    
+
     public List<Object> getMocksToBeVerifiedInOrder() {
         return mocksToBeVerifiedInOrder;
     }
 
-    public InOrderImpl(List<Object> mocksToBeVerifiedInOrder) {
+    public InOrderImpl(List<? extends Object> mocksToBeVerifiedInOrder) {
         this.mocksToBeVerifiedInOrder.addAll(mocksToBeVerifiedInOrder);
     }
 
     public <T> T verify(T mock) {
         return this.verify(mock, VerificationModeFactory.times(1));
     }
-    
+
     public <T> T verify(T mock, VerificationMode mode) {
         if (!mocksToBeVerifiedInOrder.contains(mock)) {
-            reporter.inOrderRequiresFamiliarMock();
-        } else if (!(mode instanceof VerificationInOrderMode)) {
+            throw inOrderRequiresFamiliarMock();
+        }
+        if (mode instanceof VerificationWrapper) {
+            return mockitoCore.verify(mock, new VerificationWrapperInOrderWrapper((VerificationWrapper) mode, this));
+        }  else if (!(mode instanceof VerificationInOrderMode)) {
             throw new MockitoException(mode.getClass().getSimpleName() + " is not implemented to work with InOrder");
         }
         return mockitoCore.verify(mock, new InOrderWrapper((VerificationInOrderMode) mode, this));
@@ -61,4 +66,4 @@
     public void verifyNoMoreInteractions() {
         mockitoCore.verifyNoMoreInteractionsInOrder(mocksToBeVerifiedInOrder, this);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/InternalMockHandler.java b/src/main/java/org/mockito/internal/InternalMockHandler.java
index 8bed989..2e6dc60 100644
--- a/src/main/java/org/mockito/internal/InternalMockHandler.java
+++ b/src/main/java/org/mockito/internal/InternalMockHandler.java
@@ -2,25 +2,21 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal;

-

-import java.util.List;

-

-import org.mockito.internal.stubbing.InvocationContainer;

-import org.mockito.invocation.MockHandler;

-import org.mockito.mock.MockCreationSettings;

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.VoidMethodStubbable;

-

-@SuppressWarnings("unchecked")

-public interface InternalMockHandler<T> extends MockHandler {

-

-    MockCreationSettings getMockSettings();

-

-    VoidMethodStubbable<T> voidMethodStubbable(T mock);

-    

-    void setAnswersForStubbing(List<Answer> answers);

-

-    InvocationContainer getInvocationContainer();

-

-}
\ No newline at end of file
+package org.mockito.internal;
+
+import java.util.List;
+
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+
+public interface InternalMockHandler<T> extends MockHandler {
+
+    MockCreationSettings<T> getMockSettings();
+
+    void setAnswersForStubbing(List<Answer<?>> answers);
+
+    InvocationContainer getInvocationContainer();
+
+}
diff --git a/src/main/java/org/mockito/internal/MockitoCore.java b/src/main/java/org/mockito/internal/MockitoCore.java
index 3ac4e7b..791e0d1 100644
--- a/src/main/java/org/mockito/internal/MockitoCore.java
+++ b/src/main/java/org/mockito/internal/MockitoCore.java
@@ -1,189 +1,199 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal;

-

-import java.util.Arrays;

-import java.util.List;

-

-import org.mockito.InOrder;

-import org.mockito.MockSettings;

-import org.mockito.MockingDetails;

-import org.mockito.exceptions.Reporter;

-import org.mockito.exceptions.misusing.NotAMockException;

-import org.mockito.internal.creation.MockSettingsImpl;

-import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;

-import org.mockito.internal.progress.IOngoingStubbing;

-import org.mockito.internal.progress.MockingProgress;

-import org.mockito.internal.progress.ThreadSafeMockingProgress;

-import org.mockito.internal.stubbing.InvocationContainer;

-import org.mockito.internal.stubbing.OngoingStubbingImpl;

-import org.mockito.internal.stubbing.StubberImpl;

-import org.mockito.internal.util.DefaultMockingDetails;

-import org.mockito.internal.util.MockUtil;

-import org.mockito.internal.verification.MockAwareVerificationMode;

-import org.mockito.internal.verification.VerificationDataImpl;

-import org.mockito.internal.verification.VerificationModeFactory;

-import org.mockito.internal.verification.api.InOrderContext;

-import org.mockito.internal.verification.api.VerificationDataInOrder;

-import org.mockito.internal.verification.api.VerificationDataInOrderImpl;

-import org.mockito.invocation.Invocation;

-import org.mockito.mock.MockCreationSettings;

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.DeprecatedOngoingStubbing;

-import org.mockito.stubbing.OngoingStubbing;

-import org.mockito.stubbing.Stubber;

-import org.mockito.stubbing.VoidMethodStubbable;

-import org.mockito.verification.VerificationMode;

-

-@SuppressWarnings("unchecked")

-public class MockitoCore {

-

-    private final Reporter reporter = new Reporter();

-    private final MockUtil mockUtil = new MockUtil();

-    private final MockingProgress mockingProgress = new ThreadSafeMockingProgress();

-

-    public boolean isTypeMockable(Class<?> typeToMock) {

-        return mockUtil.isTypeMockable(typeToMock);

-    }

-

-    public <T> T mock(Class<T> typeToMock, MockSettings settings) {

-        if (!MockSettingsImpl.class.isInstance(settings)) {

-            throw new IllegalArgumentException(

-                    "Unexpected implementation of '" + settings.getClass().getCanonicalName() + "'\n"

-                    + "At the moment, you cannot provide your own implementations that class.");

-        }

-        MockSettingsImpl impl = MockSettingsImpl.class.cast(settings);

-        MockCreationSettings<T> creationSettings = impl.confirm(typeToMock);

-        T mock = mockUtil.createMock(creationSettings);

-        mockingProgress.mockingStarted(mock, typeToMock);

-        return mock;

-    }

-    

-    public IOngoingStubbing stub() {

-        IOngoingStubbing stubbing = mockingProgress.pullOngoingStubbing();

-        if (stubbing == null) {

-            mockingProgress.reset();

-            reporter.missingMethodInvocation();

-        }

-        return stubbing;

-    }

-

-    public <T> DeprecatedOngoingStubbing<T> stub(T methodCall) {

-        mockingProgress.stubbingStarted();

-        return (DeprecatedOngoingStubbing) stub();

-    }

-

-    public <T> OngoingStubbing<T> when(T methodCall) {

-        mockingProgress.stubbingStarted();

-        return (OngoingStubbing) stub();

-    }

-    

-    public <T> T verify(T mock, VerificationMode mode) {

-        if (mock == null) {

-            reporter.nullPassedToVerify();

-        } else if (!mockUtil.isMock(mock)) {

-            reporter.notAMockPassedToVerify(mock.getClass());

-        }

-        mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, mode));

-        return mock;

-    }

-    

-    public <T> void reset(T ... mocks) {

-        mockingProgress.validateState();

-        mockingProgress.reset();

-        mockingProgress.resetOngoingStubbing();

-        

-        for (T m : mocks) {

-            mockUtil.resetMock(m);

-        }

-    }

-    

-    public void verifyNoMoreInteractions(Object... mocks) {

-        assertMocksNotEmpty(mocks);

-        mockingProgress.validateState();

-        for (Object mock : mocks) {

-            try {

-                if (mock == null) {

-                    reporter.nullPassedToVerifyNoMoreInteractions();

-                }

-                InvocationContainer invocations = mockUtil.getMockHandler(mock).getInvocationContainer();

-                VerificationDataImpl data = new VerificationDataImpl(invocations, null);

-                VerificationModeFactory.noMoreInteractions().verify(data);

-            } catch (NotAMockException e) {

-                reporter.notAMockPassedToVerifyNoMoreInteractions();

-            }

-        }

-    }

-

-    public void verifyNoMoreInteractionsInOrder(List<Object> mocks, InOrderContext inOrderContext) {

-        mockingProgress.validateState();

-        VerifiableInvocationsFinder finder = new VerifiableInvocationsFinder();

-        VerificationDataInOrder data = new VerificationDataInOrderImpl(inOrderContext, finder.find(mocks), null);

-        VerificationModeFactory.noMoreInteractions().verifyInOrder(data);

-    }    

-    

-    private void assertMocksNotEmpty(Object[] mocks) {

-        if (mocks == null || mocks.length == 0) {

-            reporter.mocksHaveToBePassedToVerifyNoMoreInteractions();

-        }

-    }

-    

-    public InOrder inOrder(Object... mocks) {

-        if (mocks == null || mocks.length == 0) {

-            reporter.mocksHaveToBePassedWhenCreatingInOrder();

-        }

-        for (Object mock : mocks) {

-            if (mock == null) {

-                reporter.nullPassedWhenCreatingInOrder();

-            } else if (!mockUtil.isMock(mock)) {

-                reporter.notAMockPassedWhenCreatingInOrder();

-            }

-        }

-        return new InOrderImpl(Arrays.asList(mocks));

-    }

-    

-    public Stubber doAnswer(Answer answer) {

-        mockingProgress.stubbingStarted();

-        mockingProgress.resetOngoingStubbing();

-        return new StubberImpl().doAnswer(answer);

-    }

-    

-    public <T> VoidMethodStubbable<T> stubVoid(T mock) {

-        InternalMockHandler<T> handler = mockUtil.getMockHandler(mock);

-        mockingProgress.stubbingStarted();

-        return handler.voidMethodStubbable(mock);

-    }

-

-    public void validateMockitoUsage() {

-        mockingProgress.validateState();

-    }

-

-    /**

-     * For testing purposes only. Is not the part of main API.

-     * @return last invocation

-     */

-    public Invocation getLastInvocation() {

-        OngoingStubbingImpl ongoingStubbing = ((OngoingStubbingImpl) mockingProgress.pullOngoingStubbing());

-        List<Invocation> allInvocations = ongoingStubbing.getRegisteredInvocations();

-        return allInvocations.get(allInvocations.size()-1);

-    }

-

-    public Object[] ignoreStubs(Object... mocks) {

-        for (Object m : mocks) {

-            InvocationContainer invocationContainer = new MockUtil().getMockHandler(m).getInvocationContainer();

-            List<Invocation> ins = invocationContainer.getInvocations();

-            for (Invocation in : ins) {

-                if (in.stubInfo() != null) {

-                    in.ignoreForVerification();

-                }

-            }

-        }

-        return mocks;

-    }

-

-    public MockingDetails mockingDetails(Object toInspect) {

-        return new DefaultMockingDetails(toInspect, new MockUtil());

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal;
+
+import static org.mockito.internal.exceptions.Reporter.missingMethodInvocation;
+import static org.mockito.internal.exceptions.Reporter.mocksHaveToBePassedToVerifyNoMoreInteractions;
+import static org.mockito.internal.exceptions.Reporter.mocksHaveToBePassedWhenCreatingInOrder;
+import static org.mockito.internal.exceptions.Reporter.notAMockPassedToVerify;
+import static org.mockito.internal.exceptions.Reporter.notAMockPassedToVerifyNoMoreInteractions;
+import static org.mockito.internal.exceptions.Reporter.notAMockPassedWhenCreatingInOrder;
+import static org.mockito.internal.exceptions.Reporter.nullPassedToVerify;
+import static org.mockito.internal.exceptions.Reporter.nullPassedToVerifyNoMoreInteractions;
+import static org.mockito.internal.exceptions.Reporter.nullPassedWhenCreatingInOrder;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+import static org.mockito.internal.util.MockUtil.createMock;
+import static org.mockito.internal.util.MockUtil.getMockHandler;
+import static org.mockito.internal.util.MockUtil.isMock;
+import static org.mockito.internal.util.MockUtil.resetMock;
+import static org.mockito.internal.util.MockUtil.typeMockabilityOf;
+import static org.mockito.internal.verification.VerificationModeFactory.noMoreInteractions;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import org.mockito.InOrder;
+import org.mockito.MockSettings;
+import org.mockito.MockingDetails;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.stubbing.OngoingStubbingImpl;
+import org.mockito.internal.stubbing.StubberImpl;
+import org.mockito.internal.util.DefaultMockingDetails;
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.internal.verification.VerificationDataImpl;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.internal.verification.api.VerificationDataInOrder;
+import org.mockito.internal.verification.api.VerificationDataInOrderImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.listeners.VerificationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.stubbing.Stubber;
+import org.mockito.verification.VerificationMode;
+
+@SuppressWarnings("unchecked")
+public class MockitoCore {
+
+    public boolean isTypeMockable(Class<?> typeToMock) {
+        return typeMockabilityOf(typeToMock).mockable();
+    }
+
+    public <T> T mock(Class<T> typeToMock, MockSettings settings) {
+        if (!MockSettingsImpl.class.isInstance(settings)) {
+            throw new IllegalArgumentException("Unexpected implementation of '" + settings.getClass().getCanonicalName() + "'\n" + "At the moment, you cannot provide your own implementations of that class.");
+        }
+        MockSettingsImpl impl = MockSettingsImpl.class.cast(settings);
+        MockCreationSettings<T> creationSettings = impl.confirm(typeToMock);
+        T mock = createMock(creationSettings);
+        mockingProgress().mockingStarted(mock, creationSettings);
+        return mock;
+    }
+
+    public <T> OngoingStubbing<T> when(T methodCall) {
+        MockingProgress mockingProgress = mockingProgress();
+        mockingProgress.stubbingStarted();
+        @SuppressWarnings("unchecked")
+        OngoingStubbing<T> stubbing = (OngoingStubbing<T>) mockingProgress.pullOngoingStubbing();
+        if (stubbing == null) {
+            mockingProgress.reset();
+            throw missingMethodInvocation();
+        }
+        return stubbing;
+    }
+
+    public <T> T verify(T mock, VerificationMode mode) {
+        if (mock == null) {
+            throw nullPassedToVerify();
+        }
+        if (!isMock(mock)) {
+            throw notAMockPassedToVerify(mock.getClass());
+        }
+        MockingProgress mockingProgress = mockingProgress();
+        VerificationMode actualMode = mockingProgress.maybeVerifyLazily(mode);
+        mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, actualMode, mockingProgress.verificationListeners()));
+        return mock;
+    }
+
+    public <T> void reset(T... mocks) {
+        MockingProgress mockingProgress = mockingProgress();
+        mockingProgress.validateState();
+        mockingProgress.reset();
+        mockingProgress.resetOngoingStubbing();
+
+        for (T m : mocks) {
+            resetMock(m);
+        }
+    }
+
+    public <T> void clearInvocations(T... mocks) {
+        MockingProgress mockingProgress = mockingProgress();
+        mockingProgress.validateState();
+        mockingProgress.reset();
+        mockingProgress.resetOngoingStubbing();
+
+        for (T m : mocks) {
+            getMockHandler(m).getInvocationContainer().clearInvocations();
+        }
+    }
+
+    public void verifyNoMoreInteractions(Object... mocks) {
+        assertMocksNotEmpty(mocks);
+        mockingProgress().validateState();
+        for (Object mock : mocks) {
+            try {
+                if (mock == null) {
+                    throw nullPassedToVerifyNoMoreInteractions();
+                }
+                InvocationContainer invocations = getMockHandler(mock).getInvocationContainer();
+                VerificationDataImpl data = new VerificationDataImpl(invocations, null);
+                noMoreInteractions().verify(data);
+            } catch (NotAMockException e) {
+                throw notAMockPassedToVerifyNoMoreInteractions();
+            }
+        }
+    }
+
+    public void verifyNoMoreInteractionsInOrder(List<Object> mocks, InOrderContext inOrderContext) {
+        mockingProgress().validateState();
+        VerificationDataInOrder data = new VerificationDataInOrderImpl(inOrderContext, VerifiableInvocationsFinder.find(mocks), null);
+        VerificationModeFactory.noMoreInteractions().verifyInOrder(data);
+    }
+
+    private void assertMocksNotEmpty(Object[] mocks) {
+        if (mocks == null || mocks.length == 0) {
+            throw mocksHaveToBePassedToVerifyNoMoreInteractions();
+        }
+    }
+
+    public InOrder inOrder(Object... mocks) {
+        if (mocks == null || mocks.length == 0) {
+            throw mocksHaveToBePassedWhenCreatingInOrder();
+        }
+        for (Object mock : mocks) {
+            if (mock == null) {
+                throw nullPassedWhenCreatingInOrder();
+            }
+            if (!isMock(mock)) {
+                throw notAMockPassedWhenCreatingInOrder();
+            }
+        }
+        return new InOrderImpl(Arrays.asList(mocks));
+    }
+
+    public Stubber stubber() {
+        MockingProgress mockingProgress = mockingProgress();
+        mockingProgress.stubbingStarted();
+        mockingProgress.resetOngoingStubbing();
+        return new StubberImpl();
+    }
+
+    public void validateMockitoUsage() {
+        mockingProgress().validateState();
+    }
+
+    /**
+     * For testing purposes only. Is not the part of main API.
+     *
+     * @return last invocation
+     */
+    public Invocation getLastInvocation() {
+        OngoingStubbingImpl ongoingStubbing = ((OngoingStubbingImpl) mockingProgress().pullOngoingStubbing());
+        List<Invocation> allInvocations = ongoingStubbing.getRegisteredInvocations();
+        return allInvocations.get(allInvocations.size() - 1);
+    }
+
+    public Object[] ignoreStubs(Object... mocks) {
+        for (Object m : mocks) {
+            InvocationContainer invocationContainer = getMockHandler(m).getInvocationContainer();
+            List<Invocation> ins = invocationContainer.getInvocations();
+            for (Invocation in : ins) {
+                if (in.stubInfo() != null) {
+                    in.ignoreForVerification();
+                }
+            }
+        }
+        return mocks;
+    }
+
+    public MockingDetails mockingDetails(Object toInspect) {
+        return new DefaultMockingDetails(toInspect);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/configuration/CaptorAnnotationProcessor.java b/src/main/java/org/mockito/internal/configuration/CaptorAnnotationProcessor.java
index 60b8dd8..0ccbfbc 100644
--- a/src/main/java/org/mockito/internal/configuration/CaptorAnnotationProcessor.java
+++ b/src/main/java/org/mockito/internal/configuration/CaptorAnnotationProcessor.java
@@ -22,7 +22,7 @@
                + field.getName() + "' has wrong type\n"
                + "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class.");
         }
-        Class cls = new GenericMaster().getGenericType(field);
+        Class<?> cls = new GenericMaster().getGenericType(field);
         return ArgumentCaptor.forClass(cls);
     }
 }
diff --git a/src/main/java/org/mockito/internal/configuration/ClassPathLoader.java b/src/main/java/org/mockito/internal/configuration/ClassPathLoader.java
index d31733a..67b2040 100644
--- a/src/main/java/org/mockito/internal/configuration/ClassPathLoader.java
+++ b/src/main/java/org/mockito/internal/configuration/ClassPathLoader.java
@@ -5,17 +5,9 @@
 package org.mockito.internal.configuration;
 
 import org.mockito.configuration.IMockitoConfiguration;
-import org.mockito.exceptions.base.MockitoException;
 import org.mockito.exceptions.misusing.MockitoConfigurationException;
 import org.mockito.plugins.MockMaker;
-import org.mockito.plugins.StackTraceCleanerProvider;
 
-import java.io.*;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
 
 /**
  * Loads configuration or extension points available in the classpath.
@@ -62,10 +54,10 @@
      */
     @SuppressWarnings({"unchecked"})
     public IMockitoConfiguration loadConfiguration() {
-        //Trying to get config from classpath
-        Class configClass;
+        // Trying to get config from classpath
+        Class<?> configClass;
         try {
-            configClass = (Class) Class.forName(MOCKITO_CONFIGURATION_CLASS_NAME);
+            configClass = Class.forName(MOCKITO_CONFIGURATION_CLASS_NAME);
         } catch (ClassNotFoundException e) {
             //that's ok, it means there is no global config, using default one.
             return null;
@@ -79,4 +71,4 @@
             throw new MockitoConfigurationException("Unable to instantiate " + MOCKITO_CONFIGURATION_CLASS_NAME +" class. Does it have a safe, no-arg constructor?", e);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/configuration/DefaultAnnotationEngine.java b/src/main/java/org/mockito/internal/configuration/DefaultAnnotationEngine.java
deleted file mode 100644
index eaf1538..0000000
--- a/src/main/java/org/mockito/internal/configuration/DefaultAnnotationEngine.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.configuration;

-

-import org.mockito.Captor;

-import org.mockito.Mock;

-import org.mockito.MockitoAnnotations;

-import org.mockito.configuration.AnnotationEngine;

-import org.mockito.exceptions.Reporter;

-import org.mockito.exceptions.base.MockitoException;

-import org.mockito.internal.util.reflection.FieldSetter;

-

-import java.lang.annotation.Annotation;

-import java.lang.reflect.Field;

-import java.util.HashMap;

-import java.util.Map;

-

-/**

- * Initializes fields annotated with &#64;{@link org.mockito.Mock} or &#64;{@link org.mockito.Captor}.

- *

- * <p>

- * The {@link #process(Class, Object)} method implementation <strong>does not</strong> process super classes!

- *

- * @see MockitoAnnotations

- */

-@SuppressWarnings("unchecked")

-public class DefaultAnnotationEngine implements AnnotationEngine {

-    private final Map<Class<? extends Annotation>, FieldAnnotationProcessor<?>> annotationProcessorMap = new HashMap<Class<? extends Annotation>, FieldAnnotationProcessor<?>>();

-

-    public DefaultAnnotationEngine() {

-        registerAnnotationProcessor(Mock.class, new MockAnnotationProcessor());

-        registerAnnotationProcessor(MockitoAnnotations.Mock.class, new MockitoAnnotationsMockAnnotationProcessor());

-        registerAnnotationProcessor(Captor.class, new CaptorAnnotationProcessor());

-    }

-

-    /* (non-Javadoc)

-    * @see org.mockito.AnnotationEngine#createMockFor(java.lang.annotation.Annotation, java.lang.reflect.Field)

-    */

-    @SuppressWarnings("deprecation")

-    public Object createMockFor(Annotation annotation, Field field) {

-        return forAnnotation(annotation).process(annotation, field);

-    }

-

-    private <A extends Annotation> FieldAnnotationProcessor<A> forAnnotation(A annotation) {

-        if (annotationProcessorMap.containsKey(annotation.annotationType())) {

-            return (FieldAnnotationProcessor<A>) annotationProcessorMap.get(annotation.annotationType());

-        }

-        return new FieldAnnotationProcessor<A>() {

-            public Object process(A annotation, Field field) {

-                return null;

-            }

-        };

-    }

-

-    private <A extends Annotation> void registerAnnotationProcessor(Class<A> annotationClass, FieldAnnotationProcessor<A> fieldAnnotationProcessor) {

-        annotationProcessorMap.put(annotationClass, fieldAnnotationProcessor);

-    }

-

-    public void process(Class<?> clazz, Object testInstance) {

-        Field[] fields = clazz.getDeclaredFields();

-        for (Field field : fields) {

-            boolean alreadyAssigned = false;

-            for(Annotation annotation : field.getAnnotations()) {           

-                Object mock = createMockFor(annotation, field);

-                if (mock != null) {

-                    throwIfAlreadyAssigned(field, alreadyAssigned);                    

-                    alreadyAssigned = true;                    

-                    try {

-                        new FieldSetter(testInstance, field).set(mock);

-                    } catch (Exception e) {

-                        throw new MockitoException("Problems setting field " + field.getName() + " annotated with "

-                                + annotation, e);

-                    }

-                }        

-            }

-        }

-    }

-    

-    void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) {

-        if (alreadyAssigned) {

-            new Reporter().moreThanOneAnnotationNotAllowed(field.getName());

-        }

-    }

-

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/configuration/DefaultInjectionEngine.java b/src/main/java/org/mockito/internal/configuration/DefaultInjectionEngine.java
index ad4e879..e5e98a1 100644
--- a/src/main/java/org/mockito/internal/configuration/DefaultInjectionEngine.java
+++ b/src/main/java/org/mockito/internal/configuration/DefaultInjectionEngine.java
@@ -2,27 +2,27 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.configuration;

-

-import org.mockito.internal.configuration.injection.MockInjection;

-

-import java.lang.reflect.Field;

-import java.util.Set;

-

-/**

- * Inject mock/spies dependencies for fields annotated with &#064;InjectMocks

- * <p/>

- * See {@link org.mockito.MockitoAnnotations}

- */

-public class DefaultInjectionEngine {

-

-    public void injectMocksOnFields(Set<Field> needingInjection, Set<Object> mocks, Object testClassInstance) {

-        MockInjection.onFields(needingInjection, testClassInstance)

-                .withMocks(mocks)

-                .tryConstructorInjection()

-                .tryPropertyOrFieldInjection()

-                .handleSpyAnnotation()

-                .apply();

-    }

-

-}

+package org.mockito.internal.configuration;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+import org.mockito.internal.configuration.injection.MockInjection;
+
+/**
+ * Inject mock/spies dependencies for fields annotated with &#064;InjectMocks
+ * <p/>
+ * See {@link org.mockito.MockitoAnnotations}
+ */
+public class DefaultInjectionEngine {
+
+    public void injectMocksOnFields(Set<Field> needingInjection, Set<Object> mocks, Object testClassInstance) {
+        MockInjection.onFields(needingInjection, testClassInstance)
+                .withMocks(mocks)
+                .tryConstructorInjection()
+                .tryPropertyOrFieldInjection()
+                .handleSpyAnnotation()
+                .apply();
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/configuration/GlobalConfiguration.java b/src/main/java/org/mockito/internal/configuration/GlobalConfiguration.java
index 99f3dd9..4ac027a 100644
--- a/src/main/java/org/mockito/internal/configuration/GlobalConfiguration.java
+++ b/src/main/java/org/mockito/internal/configuration/GlobalConfiguration.java
@@ -1,69 +1,73 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.configuration;

-

-import org.mockito.ReturnValues;

-import org.mockito.configuration.AnnotationEngine;

-import org.mockito.configuration.DefaultMockitoConfiguration;

-import org.mockito.configuration.IMockitoConfiguration;

-import org.mockito.stubbing.Answer;

-

-import java.io.Serializable;

-

-/**

- * Thread-safe wrapper on user-defined org.mockito.configuration.MockitoConfiguration implementation

- */

-@SuppressWarnings("deprecation")//suppressed until ReturnValues are removed

-public class GlobalConfiguration implements IMockitoConfiguration, Serializable {

-    private static final long serialVersionUID = -2860353062105505938L;

-    

-    private static final ThreadLocal<IMockitoConfiguration> GLOBAL_CONFIGURATION = new ThreadLocal<IMockitoConfiguration>();

-

-    //back door for testing

-    IMockitoConfiguration getIt() {

-        return GLOBAL_CONFIGURATION.get();

-    }

-

-    public GlobalConfiguration() {

-        //Configuration should be loaded only once but I cannot really test it

-        if (GLOBAL_CONFIGURATION.get() == null) {

-            GLOBAL_CONFIGURATION.set(createConfig());

-        }

-    }

-

-    private IMockitoConfiguration createConfig() {

-        IMockitoConfiguration defaultConfiguration = new DefaultMockitoConfiguration();

-        IMockitoConfiguration config = new ClassPathLoader().loadConfiguration();

-        if (config != null) {

-            return config;

-        } else {

-            return defaultConfiguration;

-        }

-    }

-

-    public static void validate() {

-        new GlobalConfiguration();

-    }

-

-    public ReturnValues getReturnValues() {

-        return GLOBAL_CONFIGURATION.get().getReturnValues();

-    }

-

-    public AnnotationEngine getAnnotationEngine() {

-        return GLOBAL_CONFIGURATION.get().getAnnotationEngine();

-    }

-

-    public boolean cleansStackTrace() {

-        return GLOBAL_CONFIGURATION.get().cleansStackTrace();

-    }

-    

-    public boolean enableClassCache() {

-        return GLOBAL_CONFIGURATION.get().enableClassCache();

-    }

-

-    public Answer<Object> getDefaultAnswer() {

-        return GLOBAL_CONFIGURATION.get().getDefaultAnswer();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import java.io.Serializable;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.configuration.DefaultMockitoConfiguration;
+import org.mockito.configuration.IMockitoConfiguration;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Thread-safe wrapper on user-defined org.mockito.configuration.MockitoConfiguration implementation
+ */
+public class GlobalConfiguration implements IMockitoConfiguration, Serializable {
+    private static final long serialVersionUID = -2860353062105505938L;
+
+    private static final ThreadLocal<IMockitoConfiguration> GLOBAL_CONFIGURATION = new ThreadLocal<IMockitoConfiguration>();
+
+    //back door for testing
+    IMockitoConfiguration getIt() {
+        return GLOBAL_CONFIGURATION.get();
+    }
+
+    public GlobalConfiguration() {
+        //Configuration should be loaded only once but I cannot really test it
+        if (GLOBAL_CONFIGURATION.get() == null) {
+            GLOBAL_CONFIGURATION.set(createConfig());
+        }
+    }
+
+    private IMockitoConfiguration createConfig() {
+        IMockitoConfiguration defaultConfiguration = new DefaultMockitoConfiguration();
+        IMockitoConfiguration config = new ClassPathLoader().loadConfiguration();
+        if (config != null) {
+            return config;
+        } else {
+            return defaultConfiguration;
+        }
+    }
+
+    public static void validate() {
+        new GlobalConfiguration();
+    }
+
+    public AnnotationEngine getAnnotationEngine() {
+        return GLOBAL_CONFIGURATION.get().getAnnotationEngine();
+    }
+
+    public org.mockito.plugins.AnnotationEngine tryGetPluginAnnotationEngine() {
+        IMockitoConfiguration configuration = GLOBAL_CONFIGURATION.get();
+        if (configuration.getClass() == DefaultMockitoConfiguration.class) {
+            return Plugins.getAnnotationEngine();
+        }
+        return configuration.getAnnotationEngine();
+    }
+
+
+
+    public boolean cleansStackTrace() {
+        return GLOBAL_CONFIGURATION.get().cleansStackTrace();
+    }
+
+    public boolean enableClassCache() {
+        return GLOBAL_CONFIGURATION.get().enableClassCache();
+    }
+
+    public Answer<Object> getDefaultAnswer() {
+        return GLOBAL_CONFIGURATION.get().getDefaultAnswer();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/configuration/IndependentAnnotationEngine.java b/src/main/java/org/mockito/internal/configuration/IndependentAnnotationEngine.java
new file mode 100644
index 0000000..d78476a
--- /dev/null
+++ b/src/main/java/org/mockito/internal/configuration/IndependentAnnotationEngine.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.plugins.AnnotationEngine;
+
+import static org.mockito.internal.exceptions.Reporter.moreThanOneAnnotationNotAllowed;
+import static org.mockito.internal.util.reflection.FieldSetter.setField;
+
+/**
+ * Initializes fields annotated with &#64;{@link org.mockito.Mock} or &#64;{@link org.mockito.Captor}.
+ *
+ * <p>
+ * The {@link #process(Class, Object)} method implementation <strong>does not</strong> process super classes!
+ *
+ * @see MockitoAnnotations
+ */
+@SuppressWarnings("unchecked")
+public class IndependentAnnotationEngine implements AnnotationEngine, org.mockito.configuration.AnnotationEngine {
+    private final Map<Class<? extends Annotation>, FieldAnnotationProcessor<?>> annotationProcessorMap = new HashMap<Class<? extends Annotation>, FieldAnnotationProcessor<?>>();
+
+    public IndependentAnnotationEngine() {
+        registerAnnotationProcessor(Mock.class, new MockAnnotationProcessor());
+        registerAnnotationProcessor(Captor.class, new CaptorAnnotationProcessor());
+    }
+
+    private Object createMockFor(Annotation annotation, Field field) {
+        return forAnnotation(annotation).process(annotation, field);
+    }
+
+    private <A extends Annotation> FieldAnnotationProcessor<A> forAnnotation(A annotation) {
+        if (annotationProcessorMap.containsKey(annotation.annotationType())) {
+            return (FieldAnnotationProcessor<A>) annotationProcessorMap.get(annotation.annotationType());
+        }
+        return new FieldAnnotationProcessor<A>() {
+            public Object process(A annotation, Field field) {
+                return null;
+            }
+        };
+    }
+
+    private <A extends Annotation> void registerAnnotationProcessor(Class<A> annotationClass, FieldAnnotationProcessor<A> fieldAnnotationProcessor) {
+        annotationProcessorMap.put(annotationClass, fieldAnnotationProcessor);
+    }
+
+    @Override
+    public void process(Class<?> clazz, Object testInstance) {
+        Field[] fields = clazz.getDeclaredFields();
+        for (Field field : fields) {
+            boolean alreadyAssigned = false;
+            for(Annotation annotation : field.getAnnotations()) {
+                Object mock = createMockFor(annotation, field);
+                if (mock != null) {
+                    throwIfAlreadyAssigned(field, alreadyAssigned);
+                    alreadyAssigned = true;
+                    try {
+                        setField(testInstance, field,mock);
+                    } catch (Exception e) {
+                        throw new MockitoException("Problems setting field " + field.getName() + " annotated with "
+                                + annotation, e);
+                    }
+                }
+            }
+        }
+    }
+
+    void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) {
+        if (alreadyAssigned) {
+            throw moreThanOneAnnotationNotAllowed(field.getName());
+        }
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/configuration/InjectingAnnotationEngine.java b/src/main/java/org/mockito/internal/configuration/InjectingAnnotationEngine.java
index 530038b..6cb5fb1 100644
--- a/src/main/java/org/mockito/internal/configuration/InjectingAnnotationEngine.java
+++ b/src/main/java/org/mockito/internal/configuration/InjectingAnnotationEngine.java
@@ -1,103 +1,94 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.configuration;

-

-import org.mockito.*;

-import org.mockito.configuration.AnnotationEngine;

-import org.mockito.internal.configuration.injection.scanner.InjectMocksScanner;

-import org.mockito.internal.configuration.injection.scanner.MockScanner;

-

-import java.lang.annotation.Annotation;

-import java.lang.reflect.Field;

-import java.util.HashSet;

-import java.util.Set;

-

-import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;

-

-/**

- * See {@link MockitoAnnotations}

- */

-@SuppressWarnings({"deprecation", "unchecked"})

-public class InjectingAnnotationEngine implements AnnotationEngine {

-    private final AnnotationEngine delegate = new DefaultAnnotationEngine();

-    private final AnnotationEngine spyAnnotationEngine = new SpyAnnotationEngine();

-

-    /***

-     * Create a mock using {@link DefaultAnnotationEngine}

-     *

-     * @see org.mockito.internal.configuration.DefaultAnnotationEngine

-     * @see org.mockito.configuration.AnnotationEngine#createMockFor(java.lang.annotation.Annotation, java.lang.reflect.Field)

-     */

-    @Deprecated

-    public Object createMockFor(Annotation annotation, Field field) {

-        return delegate.createMockFor(annotation, field);

-    }

-

-    /**

-     * Process the fields of the test instance and create Mocks, Spies, Captors and inject them on fields

-     * annotated &#64;InjectMocks.

-     *

-     * <p>

-     * This code process the test class and the super classes.

-     * <ol>

-     * <li>First create Mocks, Spies, Captors.</li>

-     * <li>Then try to inject them.</li>

-     * </ol>

-     *

-     * @param clazz Not used

-     * @param testInstance The instance of the test, should not be null.

-     *

-     * @see org.mockito.configuration.AnnotationEngine#process(Class, Object)

-     */

-    public void process(Class<?> clazz, Object testInstance) {

-        processIndependentAnnotations(testInstance.getClass(), testInstance);

-        processInjectMocks(testInstance.getClass(), testInstance);

-    }

-

-    private void processInjectMocks(final Class<?> clazz, final Object testInstance) {

-        Class<?> classContext = clazz;

-        while (classContext != Object.class) {

-            injectMocks(testInstance);

-            classContext = classContext.getSuperclass();

-        }

-    }

-

-    private void processIndependentAnnotations(final Class<?> clazz, final Object testInstance) {

-        Class<?> classContext = clazz;

-        while (classContext != Object.class) {

-            //this will create @Mocks, @Captors, etc:

-            delegate.process(classContext, testInstance);

-            //this will create @Spies:

-            spyAnnotationEngine.process(classContext, testInstance);

-

-            classContext = classContext.getSuperclass();

-        }

-    }

-

-

-    /**

-     * Initializes mock/spies dependencies for objects annotated with

-     * &#064;InjectMocks for given testClassInstance.

-     * <p>

-     * See examples in javadoc for {@link MockitoAnnotations} class.

-     * 

-     * @param testClassInstance

-     *            Test class, usually <code>this</code>

-     */

-    public void injectMocks(final Object testClassInstance) {

-        Class<?> clazz = testClassInstance.getClass();

-        Set<Field> mockDependentFields = new HashSet<Field>();

-        Set<Object> mocks = newMockSafeHashSet();

-        

-        while (clazz != Object.class) {

-            new InjectMocksScanner(clazz).addTo(mockDependentFields);

-            new MockScanner(testClassInstance, clazz).addPreparedMocks(mocks);

-            clazz = clazz.getSuperclass();

-        }

-        

-        new DefaultInjectionEngine().injectMocksOnFields(mockDependentFields, mocks, testClassInstance);

-    }

-

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.configuration.injection.scanner.InjectMocksScanner;
+import org.mockito.internal.configuration.injection.scanner.MockScanner;
+import org.mockito.plugins.AnnotationEngine;
+
+import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+
+/**
+ * See {@link MockitoAnnotations}
+ */
+public class InjectingAnnotationEngine implements AnnotationEngine, org.mockito.configuration.AnnotationEngine {
+    private final AnnotationEngine delegate = new IndependentAnnotationEngine();
+    private final AnnotationEngine spyAnnotationEngine = new SpyAnnotationEngine();
+
+    /**
+     * Process the fields of the test instance and create Mocks, Spies, Captors and inject them on fields
+     * annotated &#64;InjectMocks.
+     *
+     * <p>
+     * This code process the test class and the super classes.
+     * <ol>
+     * <li>First create Mocks, Spies, Captors.</li>
+     * <li>Then try to inject them.</li>
+     * </ol>
+     *
+     * @param clazz Not used
+     * @param testInstance The instance of the test, should not be null.
+     *
+     * @see org.mockito.plugins.AnnotationEngine#process(Class, Object)
+     */
+    public void process(Class<?> clazz, Object testInstance) {
+        processIndependentAnnotations(testInstance.getClass(), testInstance);
+        processInjectMocks(testInstance.getClass(), testInstance);
+    }
+
+    private void processInjectMocks(final Class<?> clazz, final Object testInstance) {
+        Class<?> classContext = clazz;
+        while (classContext != Object.class) {
+            injectMocks(testInstance);
+            classContext = classContext.getSuperclass();
+        }
+    }
+
+    private void processIndependentAnnotations(final Class<?> clazz, final Object testInstance) {
+        Class<?> classContext = clazz;
+        while (classContext != Object.class) {
+            //this will create @Mocks, @Captors, etc:
+            delegate.process(classContext, testInstance);
+            //this will create @Spies:
+            spyAnnotationEngine.process(classContext, testInstance);
+
+            classContext = classContext.getSuperclass();
+        }
+    }
+
+
+    /**
+     * Initializes mock/spies dependencies for objects annotated with
+     * &#064;InjectMocks for given testClassInstance.
+     * <p>
+     * See examples in javadoc for {@link MockitoAnnotations} class.
+     *
+     * @param testClassInstance
+     *            Test class, usually <code>this</code>
+     */
+    public void injectMocks(final Object testClassInstance) {
+        Class<?> clazz = testClassInstance.getClass();
+        Set<Field> mockDependentFields = new HashSet<Field>();
+        Set<Object> mocks = newMockSafeHashSet();
+
+        while (clazz != Object.class) {
+            new InjectMocksScanner(clazz).addTo(mockDependentFields);
+            new MockScanner(testClassInstance, clazz).addPreparedMocks(mocks);
+            onInjection(testClassInstance, clazz, mockDependentFields, mocks);
+            clazz = clazz.getSuperclass();
+        }
+
+        new DefaultInjectionEngine().injectMocksOnFields(mockDependentFields, mocks, testClassInstance);
+    }
+
+    protected void onInjection(Object testClassInstance, Class<?> clazz, Set<Field> mockDependentFields, Set<Object> mocks) {
+
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java b/src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java
index 4d55074..40cb992 100644
--- a/src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java
+++ b/src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java
@@ -25,11 +25,11 @@
             mockSettings.name(annotation.name());
         }
         if(annotation.serializable()){
-        	mockSettings.serializable();
+            mockSettings.serializable();
         }
 
         // see @Mock answer default value
-        mockSettings.defaultAnswer(annotation.answer().get());
+        mockSettings.defaultAnswer(annotation.answer());
         return Mockito.mock(field.getType(), mockSettings);
     }
 }
diff --git a/src/main/java/org/mockito/internal/configuration/MockitoAnnotationsMockAnnotationProcessor.java b/src/main/java/org/mockito/internal/configuration/MockitoAnnotationsMockAnnotationProcessor.java
deleted file mode 100644
index e8f7502..0000000
--- a/src/main/java/org/mockito/internal/configuration/MockitoAnnotationsMockAnnotationProcessor.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.configuration;
-
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations.Mock;
-
-import java.lang.reflect.Field;
-
-/**
- * Instantiates a mock on a field annotated by {@link Mock}
- */
-@SuppressWarnings("deprecation")
-public class MockitoAnnotationsMockAnnotationProcessor implements FieldAnnotationProcessor<Mock> {
-
-    public Object process(Mock annotation, Field field) {
-        return Mockito.mock(field.getType(), field.getName());
-    }
-}
diff --git a/src/main/java/org/mockito/internal/configuration/SpyAnnotationEngine.java b/src/main/java/org/mockito/internal/configuration/SpyAnnotationEngine.java
index aef8ceb..a80efbe 100644
--- a/src/main/java/org/mockito/internal/configuration/SpyAnnotationEngine.java
+++ b/src/main/java/org/mockito/internal/configuration/SpyAnnotationEngine.java
@@ -4,19 +4,25 @@
  */
 package org.mockito.internal.configuration;
 
-import org.mockito.*;
-import org.mockito.configuration.AnnotationEngine;
-import org.mockito.exceptions.Reporter;
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.util.MockUtil;
-
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.plugins.AnnotationEngine;
 
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.withSettings;
+import static org.mockito.internal.exceptions.Reporter.unsupportedCombinationOfAnnotations;
+import static org.mockito.internal.util.StringUtil.join;
 
 /**
  * Process fields annotated with &#64;Spy.
@@ -37,34 +43,26 @@
  * <p>This engine will fail, if the field is also annotated with incompatible Mockito annotations.
  */
 @SuppressWarnings({"unchecked"})
-public class SpyAnnotationEngine implements AnnotationEngine {
+public class SpyAnnotationEngine implements AnnotationEngine, org.mockito.configuration.AnnotationEngine {
 
-    public Object createMockFor(Annotation annotation, Field field) {
-        return null;
-    }
-
-    @SuppressWarnings("deprecation") // for MockitoAnnotations.Mock
+    @Override
     public void process(Class<?> context, Object testInstance) {
         Field[] fields = context.getDeclaredFields();
         for (Field field : fields) {
             if (field.isAnnotationPresent(Spy.class) && !field.isAnnotationPresent(InjectMocks.class)) {
-                assertNoIncompatibleAnnotations(Spy.class, field, Mock.class, org.mockito.MockitoAnnotations.Mock.class, Captor.class);
+                assertNoIncompatibleAnnotations(Spy.class, field, Mock.class, Captor.class);
                 field.setAccessible(true);
                 Object instance;
                 try {
                     instance = field.get(testInstance);
-                    assertNotInterface(instance, field.getType());
-                    if (new MockUtil().isMock(instance)) {
+                    if (MockUtil.isMock(instance)) {
                         // instance has been spied earlier
                         // for example happens when MockitoAnnotations.initMocks is called two times.
                         Mockito.reset(instance);
                     } else if (instance != null) {
-                        field.set(testInstance, Mockito.mock(instance.getClass(), withSettings()
-                                .spiedInstance(instance)
-                                .defaultAnswer(Mockito.CALLS_REAL_METHODS)
-                                .name(field.getName())));
+                        field.set(testInstance, spyInstance(field, instance));
                     } else {
-                        field.set(testInstance, newSpyInstance(testInstance, field));
+                        field.set(testInstance, spyNewInstance(testInstance, field));
                     }
                 } catch (Exception e) {
                     throw new MockitoException("Unable to initialize @Spy annotated field '" + field.getName() + "'.\n" + e.getMessage(), e);
@@ -73,56 +71,76 @@
         }
     }
 
-    private static void assertNotInterface(Object testInstance, Class<?> type) {
-        type = testInstance != null? testInstance.getClass() : type;
-        if (type.isInterface()) {
-            throw new MockitoException("Type '" + type.getSimpleName() + "' is an interface and it cannot be spied on.");
-        }
+    private static Object spyInstance(Field field, Object instance) {
+        return Mockito.mock(instance.getClass(),
+                            withSettings().spiedInstance(instance)
+                                                           .defaultAnswer(CALLS_REAL_METHODS)
+                                                           .name(field.getName()));
     }
 
-    private static Object newSpyInstance(Object testInstance, Field field)
+    private static Object spyNewInstance(Object testInstance, Field field)
             throws InstantiationException, IllegalAccessException, InvocationTargetException {
-        MockSettings settings = withSettings()
-                .defaultAnswer(Mockito.CALLS_REAL_METHODS)
-                .name(field.getName());
+        MockSettings settings = withSettings().defaultAnswer(CALLS_REAL_METHODS)
+                                              .name(field.getName());
         Class<?> type = field.getType();
         if (type.isInterface()) {
             return Mockito.mock(type, settings.useConstructor());
         }
-        if (!Modifier.isStatic(type.getModifiers())) {
-            Class<?> enclosing = type.getEnclosingClass();
-            if (enclosing != null) {
-                if (!enclosing.isInstance(testInstance)) {
-                    throw new MockitoException("@Spy annotation can only initialize inner classes declared in the test. "
-                            + "Inner class: '" + type.getSimpleName() + "', "
-                            + "outer class: '" + enclosing.getSimpleName() + "'.");
-                }
-                return Mockito.mock(type, settings
-                        .useConstructor()
-                        .outerInstance(testInstance));
-            }
+        int modifiers = type.getModifiers();
+        if (typeIsPrivateAbstractInnerClass(type, modifiers)) {
+            throw new MockitoException(join("@Spy annotation can't initialize private abstract inner classes.",
+                                            "  inner class: '" + type.getSimpleName() + "'",
+                                            "  outer class: '" + type.getEnclosingClass().getSimpleName() + "'",
+                                            "",
+                                            "You should augment the visibility of this inner class"));
         }
-        Constructor<?> constructor;
-        try {
-            constructor = type.getDeclaredConstructor();
-        } catch (NoSuchMethodException e) {
-            throw new MockitoException("Please ensure that the type '" + type.getSimpleName() + "' has 0-arg constructor.");
+        if (typeIsNonStaticInnerClass(type, modifiers)) {
+            Class<?> enclosing = type.getEnclosingClass();
+            if (!enclosing.isInstance(testInstance)) {
+                throw new MockitoException(join("@Spy annotation can only initialize inner classes declared in the test.",
+                                                "  inner class: '" + type.getSimpleName() + "'",
+                                                "  outer class: '" + enclosing.getSimpleName() + "'",
+                                                ""));
+            }
+            return Mockito.mock(type, settings.useConstructor()
+                                              .outerInstance(testInstance));
         }
 
+        Constructor<?> constructor = noArgConstructorOf(type);
         if (Modifier.isPrivate(constructor.getModifiers())) {
             constructor.setAccessible(true);
-            return Mockito.mock(type, settings
-                    .spiedInstance(constructor.newInstance()));
+            return Mockito.mock(type, settings.spiedInstance(constructor.newInstance()));
         } else {
             return Mockito.mock(type, settings.useConstructor());
         }
     }
 
+    private static Constructor<?> noArgConstructorOf(Class<?> type) {
+        Constructor<?> constructor;
+        try {
+            constructor = type.getDeclaredConstructor();
+        } catch (NoSuchMethodException e) {
+            throw new MockitoException("Please ensure that the type '" + type.getSimpleName() + "' has a no-arg constructor.");
+        }
+        return constructor;
+    }
+
+    private static boolean typeIsNonStaticInnerClass(Class<?> type, int modifiers) {
+        return !Modifier.isStatic(modifiers) && type.getEnclosingClass() != null;
+    }
+
+    private static boolean typeIsPrivateAbstractInnerClass(Class<?> type, int modifiers) {
+        return Modifier.isPrivate(modifiers) && Modifier.isAbstract(modifiers) && type.getEnclosingClass() != null;
+    }
+
     //TODO duplicated elsewhere
-    void assertNoIncompatibleAnnotations(Class annotation, Field field, Class... undesiredAnnotations) {
-        for (Class u : undesiredAnnotations) {
+    private static void assertNoIncompatibleAnnotations(Class<? extends Annotation> annotation,
+                                                        Field field,
+                                                        Class<? extends Annotation>... undesiredAnnotations) {
+        for (Class<? extends Annotation> u : undesiredAnnotations) {
             if (field.isAnnotationPresent(u)) {
-                new Reporter().unsupportedCombinationOfAnnotations(annotation.getSimpleName(), annotation.getClass().getSimpleName());
+                throw unsupportedCombinationOfAnnotations(annotation.getSimpleName(),
+                                                          annotation.getClass().getSimpleName());
             }
         }
     }
diff --git a/src/main/java/org/mockito/internal/configuration/injection/ConstructorInjection.java b/src/main/java/org/mockito/internal/configuration/injection/ConstructorInjection.java
index 10c01d1..ffece34 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/ConstructorInjection.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/ConstructorInjection.java
@@ -5,12 +5,13 @@
 
 package org.mockito.internal.configuration.injection;
 
-import org.mockito.exceptions.Reporter;
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.internal.util.reflection.FieldInitializationReport;
 import org.mockito.internal.util.reflection.FieldInitializer;
 import org.mockito.internal.util.reflection.FieldInitializer.ConstructorArgumentResolver;
 
+import static org.mockito.internal.exceptions.Reporter.fieldInitialisationThrewException;
+
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
@@ -37,15 +38,8 @@
  */
 public class ConstructorInjection extends MockInjectionStrategy {
 
-    private ConstructorArgumentResolver argResolver;
-
     public ConstructorInjection() { }
 
-    // visible for testing
-    ConstructorInjection(ConstructorArgumentResolver argResolver) {
-        this.argResolver = argResolver;
-    }
-
     public boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) {
         try {
             SimpleArgumentResolver simpleArgumentResolver = new SimpleArgumentResolver(mockCandidates);
@@ -55,7 +49,7 @@
         } catch (MockitoException e) {
             if(e.getCause() instanceof InvocationTargetException) {
                 Throwable realCause = e.getCause().getCause();
-                new Reporter().fieldInitialisationThrewException(field, realCause);
+                throw fieldInitialisationThrewException(field, realCause);
             }
             // other causes should be fine
             return false;
diff --git a/src/main/java/org/mockito/internal/configuration/injection/MockInjectionStrategy.java b/src/main/java/org/mockito/internal/configuration/injection/MockInjectionStrategy.java
index b5b762e..5b56eb0 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/MockInjectionStrategy.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/MockInjectionStrategy.java
@@ -16,7 +16,7 @@
     /**
      * NOP Strategy that will always try the next strategy.
      */
-    public static final MockInjectionStrategy nop() {
+    public static MockInjectionStrategy nop() {
         return new MockInjectionStrategy() {
             protected boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) {
                 return false;
diff --git a/src/main/java/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java b/src/main/java/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
index 0fc9f10..5b52a71 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
@@ -5,22 +5,28 @@
 
 package org.mockito.internal.configuration.injection;
 
-import org.mockito.exceptions.Reporter;
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.configuration.injection.filter.FinalMockCandidateFilter;
-import org.mockito.internal.configuration.injection.filter.MockCandidateFilter;
-import org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter;
-import org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter;
-import org.mockito.internal.util.collections.ListUtil;
-import org.mockito.internal.util.reflection.FieldInitializationReport;
-import org.mockito.internal.util.reflection.FieldInitializer;
+import static org.mockito.internal.exceptions.Reporter.cannotInitializeForInjectMocksAnnotation;
+import static org.mockito.internal.exceptions.Reporter.fieldInitialisationThrewException;
+import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+import static org.mockito.internal.util.reflection.SuperTypesLastSorter.sortSuperTypesLast;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
-import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.injection.filter.MockCandidateFilter;
+import org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter;
+import org.mockito.internal.configuration.injection.filter.TerminalMockCandidateFilter;
+import org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter;
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.internal.util.reflection.FieldInitializationReport;
+import org.mockito.internal.util.reflection.FieldInitializer;
+import org.mockito.internal.util.reflection.SuperTypesLastSorter;
 
 /**
  * Inject mocks using first setters then fields, if no setters available.
@@ -33,7 +39,7 @@
  *   <li>for each fields of a class in @InjectMocks type hierarchy
  *     <ul>
  *     <li>make a copy of mock candidates
- *     <li>order fields rom sub-type to super-type, then by field name
+ *     <li>order fields from sub-type to super-type, then by field name
  *     <li>for the list of fields in a class try two passes of :
  *         <ul>
  *             <li>find mock candidate by type
@@ -58,8 +64,10 @@
  */
 public class PropertyAndSetterInjection extends MockInjectionStrategy {
 
-    private final MockCandidateFilter mockCandidateFilter = new TypeBasedCandidateFilter(new NameBasedCandidateFilter(new FinalMockCandidateFilter()));
-    private final Comparator<Field> superTypesLast = new FieldTypeAndNameComparator();
+    private final MockCandidateFilter mockCandidateFilter =
+            new TypeBasedCandidateFilter(
+                    new NameBasedCandidateFilter(
+                            new TerminalMockCandidateFilter()));
 
     private final ListUtil.Filter<Field> notFinalOrStatic = new ListUtil.Filter<Field>() {
         public boolean isOut(Field object) {
@@ -69,7 +77,6 @@
 
 
     public boolean processInjection(Field injectMocksField, Object injectMocksFieldOwner, Set<Object> mockCandidates) {
-        // Set<Object> mocksToBeInjected = new HashSet<Object>(mockCandidates);
         FieldInitializationReport report = initializeInjectMocksField(injectMocksField, injectMocksFieldOwner);
 
         // for each field in the class hierarchy
@@ -77,41 +84,43 @@
         Class<?> fieldClass = report.fieldClass();
         Object fieldInstanceNeedingInjection = report.fieldInstance();
         while (fieldClass != Object.class) {
-            injectionOccurred |= injectMockCandidates(fieldClass, newMockSafeHashSet(mockCandidates), fieldInstanceNeedingInjection);
+            injectionOccurred |= injectMockCandidates(fieldClass, fieldInstanceNeedingInjection, newMockSafeHashSet(mockCandidates));
             fieldClass = fieldClass.getSuperclass();
         }
         return injectionOccurred;
     }
 
     private FieldInitializationReport initializeInjectMocksField(Field field, Object fieldOwner) {
-        FieldInitializationReport report = null;
         try {
-            report = new FieldInitializer(fieldOwner, field).initialize();
+            return new FieldInitializer(fieldOwner, field).initialize();
         } catch (MockitoException e) {
             if(e.getCause() instanceof InvocationTargetException) {
                 Throwable realCause = e.getCause().getCause();
-                new Reporter().fieldInitialisationThrewException(field, realCause);
+                throw fieldInitialisationThrewException(field, realCause);
             }
-            new Reporter().cannotInitializeForInjectMocksAnnotation(field.getName(), e);
+            throw cannotInitializeForInjectMocksAnnotation(field.getName(),e.getMessage());
         }
-        return report; // never null
     }
 
 
-    private boolean injectMockCandidates(Class<?> awaitingInjectionClazz, Set<Object> mocks, Object instance) {
-        boolean injectionOccurred = false;
-        List<Field> orderedInstanceFields = orderedInstanceFieldsFrom(awaitingInjectionClazz);
+    private boolean injectMockCandidates(Class<?> awaitingInjectionClazz, Object injectee, Set<Object> mocks) {
+        boolean injectionOccurred;
+        List<Field> orderedCandidateInjecteeFields = orderedInstanceFieldsFrom(awaitingInjectionClazz);
         // pass 1
-        injectionOccurred |= injectMockCandidatesOnFields(mocks, instance, injectionOccurred, orderedInstanceFields);
+        injectionOccurred = injectMockCandidatesOnFields(mocks, injectee, false, orderedCandidateInjecteeFields);
         // pass 2
-        injectionOccurred |= injectMockCandidatesOnFields(mocks, instance, injectionOccurred, orderedInstanceFields);
+        injectionOccurred |= injectMockCandidatesOnFields(mocks, injectee, injectionOccurred, orderedCandidateInjecteeFields);
         return injectionOccurred;
     }
 
-    private boolean injectMockCandidatesOnFields(Set<Object> mocks, Object instance, boolean injectionOccurred, List<Field> orderedInstanceFields) {
-        for (Iterator<Field> it = orderedInstanceFields.iterator(); it.hasNext(); ) {
-            Field field = it.next();
-            Object injected = mockCandidateFilter.filterCandidate(mocks, field, instance).thenInject();
+    private boolean injectMockCandidatesOnFields(Set<Object> mocks,
+                                                 Object injectee,
+                                                 boolean injectionOccurred,
+                                                 List<Field> orderedCandidateInjecteeFields) {
+        for (Iterator<Field> it = orderedCandidateInjecteeFields.iterator(); it.hasNext(); ) {
+            Field candidateField = it.next();
+            Object injected = mockCandidateFilter.filterCandidate(mocks, candidateField, orderedCandidateInjecteeFields, injectee)
+                                                 .thenInject();
             if (injected != null) {
                 injectionOccurred |= true;
                 mocks.remove(injected);
@@ -125,27 +134,6 @@
         List<Field> declaredFields = Arrays.asList(awaitingInjectionClazz.getDeclaredFields());
         declaredFields = ListUtil.filter(declaredFields, notFinalOrStatic);
 
-        Collections.sort(declaredFields, superTypesLast);
-
-        return declaredFields;
-    }
-
-    static class FieldTypeAndNameComparator implements Comparator<Field> {
-        public int compare(Field field1, Field field2) {
-            Class<?> field1Type = field1.getType();
-            Class<?> field2Type = field2.getType();
-
-            // if same type, compares on field name
-            if (field1Type == field2Type) {
-                return field1.getName().compareTo(field2.getName());
-            }
-            if(field1Type.isAssignableFrom(field2Type)) {
-                return 1;
-            }
-            if(field2Type.isAssignableFrom(field1Type)) {
-                return -1;
-            }
-            return 0;
-        }
+        return sortSuperTypesLast(declaredFields);
     }
 }
diff --git a/src/main/java/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java b/src/main/java/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java
index 963bf27..3dc0351 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java
@@ -10,12 +10,12 @@
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.internal.util.MockUtil;
 import org.mockito.internal.util.reflection.FieldReader;
-import org.mockito.internal.util.reflection.FieldSetter;
 
 import java.lang.reflect.Field;
 import java.util.Set;
 
 import static org.mockito.Mockito.withSettings;
+import static org.mockito.internal.util.reflection.FieldSetter.setField;
 
 /**
  * Handler for field annotated with &#64;InjectMocks and &#64;Spy.
@@ -35,17 +35,16 @@
         if(!fieldReader.isNull() && field.isAnnotationPresent(Spy.class)) {
             try {
                 Object instance = fieldReader.read();
-                if (new MockUtil().isMock(instance)) {
+                if (MockUtil.isMock(instance)) {
                     // A. instance has been spied earlier
                     // B. protect against multiple use of MockitoAnnotations.initMocks()
                     Mockito.reset(instance);
                 } else {
-                    new FieldSetter(fieldOwner, field).set(
-                        Mockito.mock(instance.getClass(), withSettings()
-                            .spiedInstance(instance)
-                            .defaultAnswer(Mockito.CALLS_REAL_METHODS)
-                            .name(field.getName()))
-                    );
+                    Object mock = Mockito.mock(instance.getClass(), withSettings()
+					    .spiedInstance(instance)
+					    .defaultAnswer(Mockito.CALLS_REAL_METHODS)
+					    .name(field.getName()));
+					setField(fieldOwner, field, mock);
                 }
             } catch (Exception e) {
                 throw new MockitoException("Problems initiating spied field " + field.getName(), e);
diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java b/src/main/java/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
deleted file mode 100644
index 894b113..0000000
--- a/src/main/java/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.configuration.injection.filter;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.util.reflection.BeanPropertySetter;

-import org.mockito.internal.util.reflection.FieldSetter;

-

-import java.lang.reflect.Field;

-import java.util.Collection;

-

-/**

- * This node returns an actual injecter which will be either :

- *

- * <ul>

- * <li>an {@link OngoingInjecter} that do nothing if a candidate couldn't be found</li>

- * <li>an {@link OngoingInjecter} that will try to inject the candidate trying first the property setter then if not possible try the field access</li>

- * </ul>

- */

-public class FinalMockCandidateFilter implements MockCandidateFilter {

-    public OngoingInjecter filterCandidate(final Collection<Object> mocks, final Field field, final Object fieldInstance) {

-        if(mocks.size() == 1) {

-            final Object matchingMock = mocks.iterator().next();

-

-            return new OngoingInjecter() {

-                public Object thenInject() {

-                    try {

-                        if (!new BeanPropertySetter(fieldInstance, field).set(matchingMock)) {

-                            new FieldSetter(fieldInstance, field).set(matchingMock);

-                        }

-                    } catch (RuntimeException e) {

-                        new Reporter().cannotInjectDependency(field, matchingMock, e);

-                    }

-                    return matchingMock;

-                }

-            };

-        }

-

-        return new OngoingInjecter() {

-            public Object thenInject() {

-                return null;

-            }

-        };

-

-    }

-}

diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java b/src/main/java/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
index f407f82..454d3be 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
@@ -2,17 +2,17 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.configuration.injection.filter;

-

-import java.lang.reflect.Field;

-import java.util.Collection;

-

-public interface MockCandidateFilter {

-

-    OngoingInjecter filterCandidate(

-            Collection<Object> mocks,

-            Field fieldToBeInjected,

-            Object fieldInstance

-    );

-

-}

+package org.mockito.internal.configuration.injection.filter;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+
+public interface MockCandidateFilter {
+    OngoingInjector filterCandidate(
+            Collection<Object> mocks,
+            Field candidateFieldToBeInjected,
+            List<Field> allRemainingCandidateFields,
+            Object injectee
+    );
+}
diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java b/src/main/java/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
index a5c127d..dc50e9d 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
@@ -2,33 +2,72 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.configuration.injection.filter;

-

-import org.mockito.internal.util.MockUtil;

-

-import java.lang.reflect.Field;

-import java.util.ArrayList;

-import java.util.Collection;

-import java.util.List;

-

-public class NameBasedCandidateFilter implements MockCandidateFilter {

-    private final MockCandidateFilter next;

-    private final MockUtil mockUtil = new MockUtil();

-

-    public NameBasedCandidateFilter(MockCandidateFilter next) {

-        this.next = next;

-    }

-

-    public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Object fieldInstance) {

-        List<Object> mockNameMatches = new ArrayList<Object>();

-        if(mocks.size() > 1) {

-            for (Object mock : mocks) {

-                if (field.getName().equals(mockUtil.getMockName(mock).toString())) {

-                    mockNameMatches.add(mock);

-                }

-            }

-            return next.filterCandidate(mockNameMatches, field, fieldInstance);

-        }

-        return next.filterCandidate(mocks, field, fieldInstance);

-    }

-}

+package org.mockito.internal.configuration.injection.filter;
+
+import static org.mockito.internal.util.MockUtil.getMockName;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class NameBasedCandidateFilter implements MockCandidateFilter {
+    private final MockCandidateFilter next;
+
+    public NameBasedCandidateFilter(MockCandidateFilter next) {
+        this.next = next;
+    }
+
+    public OngoingInjector filterCandidate(final Collection<Object> mocks,
+                                           final Field candidateFieldToBeInjected,
+                                           final List<Field> allRemainingCandidateFields,
+                                           final Object injectee) {
+        if (mocks.size() == 1
+                && anotherCandidateMatchesMockName(mocks, candidateFieldToBeInjected, allRemainingCandidateFields)) {
+            return OngoingInjector.nop;
+        }
+
+        return next.filterCandidate(tooMany(mocks) ? selectMatchingName(mocks, candidateFieldToBeInjected) : mocks,
+                                    candidateFieldToBeInjected,
+                                    allRemainingCandidateFields,
+                                    injectee);
+    }
+
+    private boolean tooMany(Collection<Object> mocks) {
+        return mocks.size() > 1;
+    }
+
+    private List<Object> selectMatchingName(Collection<Object> mocks, Field candidateFieldToBeInjected) {
+        List<Object> mockNameMatches = new ArrayList<Object>();
+        for (Object mock : mocks) {
+            if (candidateFieldToBeInjected.getName().equals(getMockName(mock).toString())) {
+                mockNameMatches.add(mock);
+            }
+        }
+        return mockNameMatches;
+    }
+
+    /*
+     * In this case we have to check whether we have conflicting naming
+     * fields. E.g. 2 fields of the same type, but we have to make sure
+     * we match on the correct name.
+     *
+     * Therefore we have to go through all other fields and make sure
+     * whenever we find a field that does match its name with the mock
+     * name, we should take that field instead.
+     */
+    private boolean anotherCandidateMatchesMockName(final Collection<Object> mocks,
+                                                    final Field candidateFieldToBeInjected,
+                                                    final List<Field> allRemainingCandidateFields) {
+        String mockName = getMockName(mocks.iterator().next()).toString();
+
+        for (Field otherCandidateField : allRemainingCandidateFields) {
+            if (!otherCandidateField.equals(candidateFieldToBeInjected)
+                    && otherCandidateField.getType().equals(candidateFieldToBeInjected.getType())
+                    && otherCandidateField.getName().equals(mockName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjecter.java b/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjecter.java
deleted file mode 100644
index ee905fa..0000000
--- a/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjecter.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.configuration.injection.filter;

-

-/**

- * Allow the ongoing injection of a mock candidate.

- */

-public interface OngoingInjecter {

-

-    /**

-     * Inject the mock.

-     *

-     * <p>

-     * Please check the actual implementation.

-     * </p>

-     *

-     * @return the mock that was injected, <code>null</code> otherwise.

-     */

-    Object thenInject();

-

-}

diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjector.java b/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjector.java
new file mode 100644
index 0000000..4550e1f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjector.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+/**
+ * Allow the ongoing injection of a mock candidate.
+ */
+public interface OngoingInjector {
+
+    /**
+     * Inject the mock.
+     *
+     * <p>
+     * Please check the actual implementation.
+     * </p>
+     *
+     * @return the mock that was injected, <code>null</code> otherwise.
+     */
+    Object thenInject();
+
+    /**
+     * Injector that will do nothing, and will return <code>null</code> as no mocks will be injected
+     */
+    OngoingInjector nop = new OngoingInjector() {
+        public Object thenInject() {
+            return null;
+        }
+    };
+}
diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/TerminalMockCandidateFilter.java b/src/main/java/org/mockito/internal/configuration/injection/filter/TerminalMockCandidateFilter.java
new file mode 100644
index 0000000..3a66c7e
--- /dev/null
+++ b/src/main/java/org/mockito/internal/configuration/injection/filter/TerminalMockCandidateFilter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+import org.mockito.internal.util.reflection.BeanPropertySetter;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+
+import static org.mockito.internal.exceptions.Reporter.cannotInjectDependency;
+import static org.mockito.internal.util.reflection.FieldSetter.setField;
+
+/**
+ * This node returns an actual injecter which will be either :
+ *
+ * <ul>
+ * <li>an {@link OngoingInjector} that do nothing if a candidate couldn't be found</li>
+ * <li>an {@link OngoingInjector} that will try to inject the candidate trying first the property setter then if not possible try the field access</li>
+ * </ul>
+ */
+public class TerminalMockCandidateFilter implements MockCandidateFilter {
+    public OngoingInjector filterCandidate(final Collection<Object> mocks,
+                                           final Field candidateFieldToBeInjected,
+                                           final List<Field> allRemainingCandidateFields,
+                                           final Object injectee) {
+        if(mocks.size() == 1) {
+            final Object matchingMock = mocks.iterator().next();
+
+            return new OngoingInjector() {
+                public Object thenInject() {
+                    try {
+                        if (!new BeanPropertySetter(injectee, candidateFieldToBeInjected).set(matchingMock)) {
+                            setField(injectee, candidateFieldToBeInjected,matchingMock);
+                        }
+                    } catch (RuntimeException e) {
+                        throw cannotInjectDependency(candidateFieldToBeInjected, matchingMock, e);
+                    }
+                    return matchingMock;
+                }
+            };
+        }
+
+        return OngoingInjector.nop;
+
+    }
+}
diff --git a/src/main/java/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java b/src/main/java/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
index 46067ef..7284399 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
@@ -2,29 +2,32 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.configuration.injection.filter;

-

-import java.lang.reflect.Field;

-import java.util.ArrayList;

-import java.util.Collection;

-import java.util.List;

-

-public class TypeBasedCandidateFilter implements MockCandidateFilter {

-

-    MockCandidateFilter next;

-

-    public TypeBasedCandidateFilter(MockCandidateFilter next) {

-        this.next = next;

-    }

-

-    public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Object fieldInstance) {

-        List<Object> mockTypeMatches = new ArrayList<Object>();

-        for (Object mock : mocks) {

-            if (field.getType().isAssignableFrom(mock.getClass())) {

-                mockTypeMatches.add(mock);

-            }

-        }

-

-        return next.filterCandidate(mockTypeMatches, field, fieldInstance);

-    }

-}

+package org.mockito.internal.configuration.injection.filter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class TypeBasedCandidateFilter implements MockCandidateFilter {
+
+    private final MockCandidateFilter next;
+
+    public TypeBasedCandidateFilter(MockCandidateFilter next) {
+        this.next = next;
+    }
+
+    public OngoingInjector filterCandidate(final Collection<Object> mocks,
+                                           final Field candidateFieldToBeInjected,
+                                           final List<Field> allRemainingCandidateFields,
+                                           final Object injectee) {
+        List<Object> mockTypeMatches = new ArrayList<Object>();
+        for (Object mock : mocks) {
+            if (candidateFieldToBeInjected.getType().isAssignableFrom(mock.getClass())) {
+                mockTypeMatches.add(mock);
+            }
+        }
+
+        return next.filterCandidate(mockTypeMatches, candidateFieldToBeInjected, allRemainingCandidateFields, injectee);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/configuration/injection/package-info.java b/src/main/java/org/mockito/internal/configuration/injection/package-info.java
new file mode 100644
index 0000000..ff223f3
--- /dev/null
+++ b/src/main/java/org/mockito/internal/configuration/injection/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito injection internals.
+ */
+package org.mockito.internal.configuration.injection;
diff --git a/src/main/java/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java b/src/main/java/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java
index a225b33..57d5113 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java
@@ -7,9 +7,10 @@
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.exceptions.Reporter;
 
+import static org.mockito.internal.exceptions.Reporter.unsupportedCombinationOfAnnotations;
+
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.util.HashSet;
 import java.util.Set;
@@ -17,7 +18,6 @@
 /**
  * Scan field for injection.
  */
-@SuppressWarnings("deprecation")
 public class InjectMocksScanner {
     private final Class<?> clazz;
 
@@ -45,12 +45,13 @@
      *
      * @return Fields that depends on Mock
      */
+    @SuppressWarnings("unchecked")
     private Set<Field> scan() {
         Set<Field> mockDependentFields = new HashSet<Field>();
         Field[] fields = clazz.getDeclaredFields();
         for (Field field : fields) {
             if (null != field.getAnnotation(InjectMocks.class)) {
-                assertNoAnnotations(field, Mock.class, MockitoAnnotations.Mock.class, Captor.class);
+                assertNoAnnotations(field, Mock.class, Captor.class);
                 mockDependentFields.add(field);
             }
         }
@@ -58,10 +59,10 @@
         return mockDependentFields;
     }
 
-    void assertNoAnnotations(final Field field, final Class... annotations) {
-        for (Class annotation : annotations) {
+    private static void assertNoAnnotations(Field field, Class<? extends Annotation>... annotations) {
+        for (Class<? extends Annotation> annotation : annotations) {
             if (field.isAnnotationPresent(annotation)) {
-                new Reporter().unsupportedCombinationOfAnnotations(annotation.getSimpleName(), InjectMocks.class.getSimpleName());
+                throw unsupportedCombinationOfAnnotations(annotation.getSimpleName(), InjectMocks.class.getSimpleName());
             }
         }
     }
diff --git a/src/main/java/org/mockito/internal/configuration/injection/scanner/MockScanner.java b/src/main/java/org/mockito/internal/configuration/injection/scanner/MockScanner.java
index d7f8941..1d567fe 100644
--- a/src/main/java/org/mockito/internal/configuration/injection/scanner/MockScanner.java
+++ b/src/main/java/org/mockito/internal/configuration/injection/scanner/MockScanner.java
@@ -5,7 +5,6 @@
 package org.mockito.internal.configuration.injection.scanner;
 
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 import org.mockito.internal.util.MockUtil;
 import org.mockito.internal.util.reflection.FieldReader;
@@ -19,7 +18,6 @@
  * Scan mocks, and prepare them if needed.
  */
 public class MockScanner {
-    private final MockUtil mockUtil = new MockUtil();
     private final Object instance;
     private final Class<?> clazz;
 
@@ -69,21 +67,20 @@
     private Object preparedMock(Object instance, Field field) {
         if (isAnnotatedByMockOrSpy(field)) {
             return instance;
-        } else if (isMockOrSpy(instance)) {
-            mockUtil.maybeRedefineMockName(instance, field.getName());
+        }
+        if (isMockOrSpy(instance)) {
+            MockUtil.maybeRedefineMockName(instance, field.getName());
             return instance;
         }
         return null;
     }
 
     private boolean isAnnotatedByMockOrSpy(Field field) {
-        return null != field.getAnnotation(Spy.class)
-                || null != field.getAnnotation(Mock.class)
-                || null != field.getAnnotation(MockitoAnnotations.Mock.class);
+        return field.isAnnotationPresent(Spy.class) || field.isAnnotationPresent(Mock.class);
     }
 
     private boolean isMockOrSpy(Object instance) {
-        return mockUtil.isMock(instance)
-                || mockUtil.isSpy(instance);
+        return MockUtil.isMock(instance)
+                || MockUtil.isSpy(instance);
     }
 }
diff --git a/src/main/java/org/mockito/internal/configuration/package-info.java b/src/main/java/org/mockito/internal/configuration/package-info.java
new file mode 100644
index 0000000..adc40eb
--- /dev/null
+++ b/src/main/java/org/mockito/internal/configuration/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito configuration.
+ */
+package org.mockito.internal.configuration;
diff --git a/src/main/java/org/mockito/internal/configuration/package.html b/src/main/java/org/mockito/internal/configuration/package.html
deleted file mode 100644
index 5d4669a..0000000
--- a/src/main/java/org/mockito/internal/configuration/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Mockito configuration
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/DefaultPluginSwitch.java b/src/main/java/org/mockito/internal/configuration/plugins/DefaultPluginSwitch.java
index 85c9490..e332cd9 100644
--- a/src/main/java/org/mockito/internal/configuration/plugins/DefaultPluginSwitch.java
+++ b/src/main/java/org/mockito/internal/configuration/plugins/DefaultPluginSwitch.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.configuration.plugins;
 
 import org.mockito.plugins.PluginSwitch;
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/PluginFileReader.java b/src/main/java/org/mockito/internal/configuration/plugins/PluginFileReader.java
index ec6bda6..a71a144 100644
--- a/src/main/java/org/mockito/internal/configuration/plugins/PluginFileReader.java
+++ b/src/main/java/org/mockito/internal/configuration/plugins/PluginFileReader.java
@@ -1,14 +1,16 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.configuration.plugins;
 
 import org.mockito.internal.util.io.IOUtil;
 
-import java.io.IOException;
 import java.io.InputStream;
-import java.io.Reader;
 
 class PluginFileReader {
 
-    String readPluginClass(InputStream input) throws IOException {
+    String readPluginClass(InputStream input) {
         for(String line: IOUtil.readLines(input)) {
             String stripped = stripCommentAndWhitespace(line);
             if (stripped.length() > 0) {
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/PluginFinder.java b/src/main/java/org/mockito/internal/configuration/plugins/PluginFinder.java
index 431c86e..258da72 100644
--- a/src/main/java/org/mockito/internal/configuration/plugins/PluginFinder.java
+++ b/src/main/java/org/mockito/internal/configuration/plugins/PluginFinder.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.configuration.plugins;
 
 import org.mockito.exceptions.base.MockitoException;
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/PluginLoader.java b/src/main/java/org/mockito/internal/configuration/plugins/PluginLoader.java
index e56fb0e..0b52bb8 100644
--- a/src/main/java/org/mockito/internal/configuration/plugins/PluginLoader.java
+++ b/src/main/java/org/mockito/internal/configuration/plugins/PluginLoader.java
@@ -1,40 +1,71 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.configuration.plugins;
 
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.exceptions.misusing.MockitoConfigurationException;
 import org.mockito.internal.util.collections.Iterables;
 import org.mockito.plugins.PluginSwitch;
 
 import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.net.URL;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
 
 class PluginLoader {
 
     private final PluginSwitch pluginSwitch;
 
+    private final Map<String, String> alias;
+
     public PluginLoader(PluginSwitch pluginSwitch) {
         this.pluginSwitch = pluginSwitch;
+        this.alias = new HashMap<String, String>();
+    }
+
+    /**
+     * Adds an alias for a class name to this plugin loader. Instead of the fully qualified type name,
+     * the alias can be used as a convenience name for a known plugin.
+     */
+    PluginLoader withAlias(String name, String type) {
+        alias.put(name, type);
+        return this;
     }
 
     /**
      * Scans the classpath for given pluginType. If not found, default class is used.
      */
-    <T> T loadPlugin(Class<T> pluginType, String defaultPluginClassName) {
-        T plugin = loadImpl(pluginType);
-        if (plugin != null) {
-            return plugin;
-        }
-
+    @SuppressWarnings("unchecked")
+    <T> T loadPlugin(final Class<T> pluginType, String defaultPluginClassName) {
         try {
-            // Default implementation. Use our own ClassLoader instead of the context
-            // ClassLoader, as the default implementation is assumed to be part of
-            // Mockito and may not be available via the context ClassLoader.
-            return pluginType.cast(Class.forName(defaultPluginClassName).newInstance());
-        } catch (Exception e) {
-            throw new MockitoException("Internal problem occurred, please report it. " +
-                    "Mockito is unable to load the default implementation of class that is a part of Mockito distribution. " +
-                    "Failed to load " + pluginType, e);
+            T plugin = loadImpl(pluginType);
+            if (plugin != null) {
+                return plugin;
+            }
+
+            try {
+                // Default implementation. Use our own ClassLoader instead of the context
+                // ClassLoader, as the default implementation is assumed to be part of
+                // Mockito and may not be available via the context ClassLoader.
+                return pluginType.cast(Class.forName(defaultPluginClassName).newInstance());
+            } catch (Exception e) {
+                throw new IllegalStateException("Internal problem occurred, please report it. " +
+                        "Mockito is unable to load the default implementation of class that is a part of Mockito distribution. " +
+                        "Failed to load " + pluginType, e);
+            }
+        } catch (final Throwable t) {
+            return (T) Proxy.newProxyInstance(pluginType.getClassLoader(),
+                    new Class<?>[]{pluginType},
+                    new InvocationHandler() {
+                        @Override
+                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                            throw new IllegalStateException("Could not initialize plugin: " + pluginType, t);
+                        }
+                    });
         }
     }
 
@@ -42,7 +73,7 @@
      * Equivalent to {@link java.util.ServiceLoader#load} but without requiring
      * Java 6 / Android 2.3 (Gingerbread).
      */
-    <T> T loadImpl(Class<T> service) {
+    private <T> T loadImpl(Class<T> service) {
         ClassLoader loader = Thread.currentThread().getContextClassLoader();
         if (loader == null) {
             loader = ClassLoader.getSystemClassLoader();
@@ -51,19 +82,23 @@
         try {
             resources = loader.getResources("mockito-extensions/" + service.getName());
         } catch (IOException e) {
-            throw new MockitoException("Failed to load " + service, e);
+            throw new IllegalStateException("Failed to load " + service, e);
         }
 
         try {
             String foundPluginClass = new PluginFinder(pluginSwitch).findPluginClass(Iterables.toIterable(resources));
             if (foundPluginClass != null) {
+                String aliasType = alias.get(foundPluginClass);
+                if (aliasType != null) {
+                    foundPluginClass = aliasType;
+                }
                 Class<?> pluginClass = loader.loadClass(foundPluginClass);
                 Object plugin = pluginClass.newInstance();
                 return service.cast(plugin);
             }
             return null;
         } catch (Exception e) {
-            throw new MockitoConfigurationException(
+            throw new IllegalStateException(
                     "Failed to load " + service + " implementation declared in " + resources, e);
         }
     }
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/PluginRegistry.java b/src/main/java/org/mockito/internal/configuration/plugins/PluginRegistry.java
index 7b13973..701b08c 100644
--- a/src/main/java/org/mockito/internal/configuration/plugins/PluginRegistry.java
+++ b/src/main/java/org/mockito/internal/configuration/plugins/PluginRegistry.java
@@ -1,19 +1,32 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.configuration.plugins;
 
+import org.mockito.plugins.AnnotationEngine;
+import org.mockito.plugins.InstantiatorProvider;
 import org.mockito.plugins.MockMaker;
 import org.mockito.plugins.PluginSwitch;
 import org.mockito.plugins.StackTraceCleanerProvider;
 
 class PluginRegistry {
 
-    private final PluginSwitch pluginSwitch
-            = new PluginLoader(new DefaultPluginSwitch()).loadPlugin(PluginSwitch.class, DefaultPluginSwitch.class.getName());
+    private final PluginSwitch pluginSwitch = new PluginLoader(new DefaultPluginSwitch())
+            .loadPlugin(PluginSwitch.class, DefaultPluginSwitch.class.getName());
 
-    private final MockMaker mockMaker
-            = new PluginLoader(pluginSwitch).loadPlugin(MockMaker.class, "org.mockito.internal.creation.cglib.CglibMockMaker");
+    private final MockMaker mockMaker = new PluginLoader(pluginSwitch)
+            .withAlias("mock-maker-inline", "org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker")
+            .loadPlugin(MockMaker.class, "org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker");
 
-    private final StackTraceCleanerProvider stackTraceCleanerProvider
-            = new PluginLoader(pluginSwitch).loadPlugin(StackTraceCleanerProvider.class, "org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider");
+    private final StackTraceCleanerProvider stackTraceCleanerProvider = new PluginLoader(pluginSwitch)
+            .loadPlugin(StackTraceCleanerProvider.class, "org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider");
+
+    private final InstantiatorProvider instantiatorProvider = new PluginLoader(pluginSwitch)
+            .loadPlugin(InstantiatorProvider.class, "org.mockito.internal.creation.instance.DefaultInstantiatorProvider");
+
+    private AnnotationEngine annotationEngine = new PluginLoader(pluginSwitch)
+            .loadPlugin(AnnotationEngine.class, "org.mockito.internal.configuration.InjectingAnnotationEngine");
 
     /**
      * The implementation of the stack trace cleaner
@@ -26,10 +39,30 @@
     /**
      * Returns the implementation of the mock maker available for the current runtime.
      *
-     * <p>Returns {@link org.mockito.internal.creation.cglib.CglibMockMaker} if no
+     * <p>Returns {@link org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker} if no
      * {@link org.mockito.plugins.MockMaker} extension exists or is visible in the current classpath.</p>
      */
     MockMaker getMockMaker() {
         return mockMaker;
     }
+
+    /**
+     * Returns the instantiator provider available for the current runtime.
+     *
+     * <p>Returns {@link org.mockito.internal.creation.instance.DefaultInstantiatorProvider} if no
+     * {@link org.mockito.plugins.InstantiatorProvider} extension exists or is visible in the current classpath.</p>
+     */
+    InstantiatorProvider getInstantiatorProvider() {
+      return instantiatorProvider;
+    }
+
+    /**
+     * Returns the annotation engine available for the current runtime.
+     *
+     * <p>Returns {@link org.mockito.internal.configuration.InjectingAnnotationEngine} if no
+     * {@link org.mockito.plugins.AnnotationEngine} extension exists or is visible in the current classpath.</p>
+     */
+    AnnotationEngine getAnnotationEngine() {
+        return annotationEngine;
+    }
 }
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/Plugins.java b/src/main/java/org/mockito/internal/configuration/plugins/Plugins.java
index e6a0c7f..97d243d 100644
--- a/src/main/java/org/mockito/internal/configuration/plugins/Plugins.java
+++ b/src/main/java/org/mockito/internal/configuration/plugins/Plugins.java
@@ -1,5 +1,11 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.configuration.plugins;
 
+import org.mockito.plugins.AnnotationEngine;
+import org.mockito.plugins.InstantiatorProvider;
 import org.mockito.plugins.MockMaker;
 import org.mockito.plugins.StackTraceCleanerProvider;
 
@@ -8,7 +14,7 @@
  */
 public class Plugins {
 
-    private static PluginRegistry registry = new PluginRegistry();
+    private static final PluginRegistry registry = new PluginRegistry();
 
     /**
      * The implementation of the stack trace cleaner
@@ -20,10 +26,30 @@
     /**
      * Returns the implementation of the mock maker available for the current runtime.
      *
-     * <p>Returns {@link org.mockito.internal.creation.cglib.CglibMockMaker} if no
+     * <p>Returns default mock maker if no
      * {@link org.mockito.plugins.MockMaker} extension exists or is visible in the current classpath.</p>
      */
     public static MockMaker getMockMaker() {
         return registry.getMockMaker();
     }
+
+    /**
+     * Returns the instantiator provider available for the current runtime.
+     *
+     * <p>Returns {@link org.mockito.internal.creation.instance.DefaultInstantiatorProvider} if no
+     * {@link org.mockito.plugins.InstantiatorProvider} extension exists or is visible in the current classpath.</p>
+     */
+    public static InstantiatorProvider getInstantiatorProvider() {
+      return registry.getInstantiatorProvider();
+    }
+
+    /**
+     * Returns the annotation engine available for the current runtime.
+     *
+     * <p>Returns {@link org.mockito.internal.configuration.InjectingAnnotationEngine} if no
+     * {@link org.mockito.plugins.AnnotationEngine} extension exists or is visible in the current classpath.</p>
+     */
+    public static AnnotationEngine getAnnotationEngine() {
+        return registry.getAnnotationEngine();
+    }
 }
diff --git a/src/main/java/org/mockito/internal/configuration/plugins/package-info.java b/src/main/java/org/mockito/internal/configuration/plugins/package-info.java
new file mode 100644
index 0000000..c74ae01
--- /dev/null
+++ b/src/main/java/org/mockito/internal/configuration/plugins/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito plugins configuration machinery.
+ */
+package org.mockito.internal.configuration.plugins;
diff --git a/src/main/java/org/mockito/internal/creation/DelegatingMethod.java b/src/main/java/org/mockito/internal/creation/DelegatingMethod.java
index 034694f..d9adae6 100644
--- a/src/main/java/org/mockito/internal/creation/DelegatingMethod.java
+++ b/src/main/java/org/mockito/internal/creation/DelegatingMethod.java
@@ -67,4 +67,4 @@
     public int hashCode() {
         return method.hashCode();
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/creation/MockSettingsImpl.java b/src/main/java/org/mockito/internal/creation/MockSettingsImpl.java
index c54cffe..0b76174 100644
--- a/src/main/java/org/mockito/internal/creation/MockSettingsImpl.java
+++ b/src/main/java/org/mockito/internal/creation/MockSettingsImpl.java
@@ -1,194 +1,194 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.creation;

-

-import org.mockito.MockSettings;

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.creation.settings.CreationSettings;

-import org.mockito.internal.debugging.VerboseMockInvocationLogger;

-import org.mockito.internal.util.MockCreationValidator;

-import org.mockito.internal.util.MockNameImpl;

-import org.mockito.listeners.InvocationListener;

-import org.mockito.mock.MockCreationSettings;

-import org.mockito.mock.MockName;

-import org.mockito.mock.SerializableMode;

-import org.mockito.stubbing.Answer;

-

-import java.io.Serializable;

-import java.util.HashSet;

-import java.util.List;

-import java.util.Set;

-

-import static org.mockito.internal.util.collections.Sets.newSet;

-

-@SuppressWarnings("unchecked")

-public class MockSettingsImpl<T> extends CreationSettings<T> implements MockSettings, MockCreationSettings<T> {

-

-    private static final long serialVersionUID = 4475297236197939569L;

-    private boolean useConstructor;

-    private Object outerClassInstance;

-

-    public MockSettings serializable() {

-        return serializable(SerializableMode.BASIC);

-    }

-

-    public MockSettings serializable(SerializableMode mode) {

-        this.serializableMode = mode;

-        return this;

-    }

-

-    public MockSettings extraInterfaces(Class... extraInterfaces) {

-        if (extraInterfaces == null || extraInterfaces.length == 0) {

-            new Reporter().extraInterfacesRequiresAtLeastOneInterface();

-        }

-

-        for (Class i : extraInterfaces) {

-            if (i == null) {

-                new Reporter().extraInterfacesDoesNotAcceptNullParameters();

-            } else if (!i.isInterface()) {

-                new Reporter().extraInterfacesAcceptsOnlyInterfaces(i);

-            }

-        }

-        this.extraInterfaces = newSet(extraInterfaces);

-        return this;

-    }

-

-    public MockName getMockName() {

-        return mockName;

-    }

-

-    public Set<Class> getExtraInterfaces() {

-        return extraInterfaces;

-    }

-

-    public Object getSpiedInstance() {

-        return spiedInstance;

-    }

-

-    public MockSettings name(String name) {

-        this.name = name;

-        return this;

-    }

-

-    public MockSettings spiedInstance(Object spiedInstance) {

-        this.spiedInstance = spiedInstance;

-        return this;

-    }

-

-    public MockSettings defaultAnswer(Answer defaultAnswer) {

-        this.defaultAnswer = defaultAnswer;

-        if (defaultAnswer == null) {

-            new Reporter().defaultAnswerDoesNotAcceptNullParameter();

-        }

-        return this;

-    }

-

-    public Answer<Object> getDefaultAnswer() {

-        return defaultAnswer;

-    }

-

-    public MockSettingsImpl stubOnly() {

-        this.stubOnly = true;

-        return this;

-    }

-

-    public MockSettings useConstructor() {

-        this.useConstructor = true;

-        return this;

-    }

-

-    public MockSettings outerInstance(Object outerClassInstance) {

-        this.outerClassInstance = outerClassInstance;

-        return this;

-    }

-

-    public boolean isUsingConstructor() {

-        return useConstructor;

-    }

-

-    public Object getOuterClassInstance() {

-        return outerClassInstance;

-    }

-

-    public boolean isStubOnly() {

-        return this.stubOnly;

-    }

-

-    public MockSettings verboseLogging() {

-        if (!invocationListenersContainsType(VerboseMockInvocationLogger.class)) {

-            invocationListeners(new VerboseMockInvocationLogger());

-        }

-        return this;

-    }

-

-    public MockSettings invocationListeners(InvocationListener... listeners) {

-        if (listeners == null || listeners.length == 0) {

-            new Reporter().invocationListenersRequiresAtLeastOneListener();

-        }

-        for (InvocationListener listener : listeners) {

-            if (listener == null) {

-                new Reporter().invocationListenerDoesNotAcceptNullParameters();

-            }

-            this.invocationListeners.add(listener);

-        }

-        return this;

-    }

-

-    private boolean invocationListenersContainsType(Class<?> clazz) {

-        for (InvocationListener listener : invocationListeners) {

-            if (listener.getClass().equals(clazz)) {

-                return true;

-            }

-        }

-        return false;

-    }

-

-    public List<InvocationListener> getInvocationListeners() {

-        return this.invocationListeners;

-    }

-

-    public boolean hasInvocationListeners() {

-        return !invocationListeners.isEmpty();

-    }

-

-    public Class<T> getTypeToMock() {

-        return typeToMock;

-    }

-

-    public MockCreationSettings<T> confirm(Class<T> typeToMock) {

-        return validatedSettings(typeToMock, this);

-    }

-

-    private static <T> CreationSettings<T> validatedSettings(Class<T> typeToMock, CreationSettings<T> source) {

-        MockCreationValidator validator = new MockCreationValidator();

-

-        validator.validateType(typeToMock);

-        validator.validateExtraInterfaces(typeToMock, source.getExtraInterfaces());

-        validator.validateMockedType(typeToMock, source.getSpiedInstance());

-

-        //TODO SF - add this validation and also add missing coverage

-//        validator.validateDelegatedInstance(classToMock, settings.getDelegatedInstance());

-

-        validator.validateSerializable(typeToMock, source.isSerializable());

-        validator.validateConstructorUse(source.isUsingConstructor(), source.getSerializableMode());

-

-        //TODO SF - I don't think we really need CreationSettings type

-        CreationSettings<T> settings = new CreationSettings<T>(source);

-        settings.setMockName(new MockNameImpl(source.getName(), typeToMock));

-        settings.setTypeToMock(typeToMock);

-        settings.setExtraInterfaces(prepareExtraInterfaces(source));

-        return settings;

-    }

-

-    private static Set<Class> prepareExtraInterfaces(CreationSettings settings) {

-        Set<Class> interfaces = new HashSet<Class>(settings.getExtraInterfaces());

-        if(settings.isSerializable()) {

-            interfaces.add(Serializable.class);

-        }

-        return interfaces;

-    }

-

-}

-

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation;
+
+import org.mockito.MockSettings;
+
+import static org.mockito.internal.exceptions.Reporter.*;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.debugging.VerboseMockInvocationLogger;
+import org.mockito.internal.util.MockCreationValidator;
+import org.mockito.internal.util.MockNameImpl;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.mock.SerializableMode;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.mockito.internal.util.collections.Sets.newSet;
+
+@SuppressWarnings("unchecked")
+public class MockSettingsImpl<T> extends CreationSettings<T> implements MockSettings, MockCreationSettings<T> {
+
+    private static final long serialVersionUID = 4475297236197939569L;
+    private boolean useConstructor;
+    private Object outerClassInstance;
+
+    public MockSettings serializable() {
+        return serializable(SerializableMode.BASIC);
+    }
+
+    public MockSettings serializable(SerializableMode mode) {
+        this.serializableMode = mode;
+        return this;
+    }
+
+    public MockSettings extraInterfaces(Class<?>... extraInterfaces) {
+        if (extraInterfaces == null || extraInterfaces.length == 0) {
+            throw extraInterfacesRequiresAtLeastOneInterface();
+        }
+
+        for (Class<?> i : extraInterfaces) {
+            if (i == null) {
+                throw extraInterfacesDoesNotAcceptNullParameters();
+            } else if (!i.isInterface()) {
+                throw extraInterfacesAcceptsOnlyInterfaces(i);
+            }
+        }
+        this.extraInterfaces = newSet(extraInterfaces);
+        return this;
+    }
+
+    public MockName getMockName() {
+        return mockName;
+    }
+
+    public Set<Class<?>> getExtraInterfaces() {
+        return extraInterfaces;
+    }
+
+    public Object getSpiedInstance() {
+        return spiedInstance;
+    }
+
+    public MockSettings name(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public MockSettings spiedInstance(Object spiedInstance) {
+        this.spiedInstance = spiedInstance;
+        return this;
+    }
+
+    public MockSettings defaultAnswer(Answer defaultAnswer) {
+        this.defaultAnswer = defaultAnswer;
+        if (defaultAnswer == null) {
+            throw defaultAnswerDoesNotAcceptNullParameter();
+        }
+        return this;
+    }
+
+    public Answer<Object> getDefaultAnswer() {
+        return defaultAnswer;
+    }
+
+    public MockSettingsImpl<T> stubOnly() {
+        this.stubOnly = true;
+        return this;
+    }
+
+    public MockSettings useConstructor() {
+        this.useConstructor = true;
+        return this;
+    }
+
+    public MockSettings outerInstance(Object outerClassInstance) {
+        this.outerClassInstance = outerClassInstance;
+        return this;
+    }
+
+    public boolean isUsingConstructor() {
+        return useConstructor;
+    }
+
+    public Object getOuterClassInstance() {
+        return outerClassInstance;
+    }
+
+    public boolean isStubOnly() {
+        return this.stubOnly;
+    }
+
+    public MockSettings verboseLogging() {
+        if (!invocationListenersContainsType(VerboseMockInvocationLogger.class)) {
+            invocationListeners(new VerboseMockInvocationLogger());
+        }
+        return this;
+    }
+
+    public MockSettings invocationListeners(InvocationListener... listeners) {
+        if (listeners == null || listeners.length == 0) {
+            throw invocationListenersRequiresAtLeastOneListener();
+        }
+        for (InvocationListener listener : listeners) {
+            if (listener == null) {
+                throw invocationListenerDoesNotAcceptNullParameters();
+            }
+            this.invocationListeners.add(listener);
+        }
+        return this;
+    }
+
+    private boolean invocationListenersContainsType(Class<?> clazz) {
+        for (InvocationListener listener : invocationListeners) {
+            if (listener.getClass().equals(clazz)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<InvocationListener> getInvocationListeners() {
+        return this.invocationListeners;
+    }
+
+    public boolean hasInvocationListeners() {
+        return !invocationListeners.isEmpty();
+    }
+
+    public Class<T> getTypeToMock() {
+        return typeToMock;
+    }
+
+    public MockCreationSettings<T> confirm(Class<T> typeToMock) {
+        return validatedSettings(typeToMock, this);
+    }
+
+    private static <T> CreationSettings<T> validatedSettings(Class<T> typeToMock, CreationSettings<T> source) {
+        MockCreationValidator validator = new MockCreationValidator();
+
+        validator.validateType(typeToMock);
+        validator.validateExtraInterfaces(typeToMock, source.getExtraInterfaces());
+        validator.validateMockedType(typeToMock, source.getSpiedInstance());
+
+        //TODO SF - add this validation and also add missing coverage
+//        validator.validateDelegatedInstance(classToMock, settings.getDelegatedInstance());
+
+        validator.validateConstructorUse(source.isUsingConstructor(), source.getSerializableMode());
+
+        //TODO SF - I don't think we really need CreationSettings type
+        CreationSettings<T> settings = new CreationSettings<T>(source);
+        settings.setMockName(new MockNameImpl(source.getName(), typeToMock));
+        settings.setTypeToMock(typeToMock);
+        settings.setExtraInterfaces(prepareExtraInterfaces(source));
+        return settings;
+    }
+
+    private static Set<Class<?>> prepareExtraInterfaces(CreationSettings settings) {
+        Set<Class<?>> interfaces = new HashSet<Class<?>>(settings.getExtraInterfaces());
+        if(settings.isSerializable()) {
+            interfaces.add(Serializable.class);
+        }
+        return interfaces;
+    }
+
+}
+
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyCrossClassLoaderSerializationSupport.java b/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyCrossClassLoaderSerializationSupport.java
new file mode 100644
index 0000000..f63731c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyCrossClassLoaderSerializationSupport.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.creation.bytebuddy;
+
+import org.mockito.Incubating;
+import org.mockito.exceptions.base.MockitoSerializationIssue;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.mock.SerializableMode;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.ForWriteReplace;
+import static org.mockito.internal.util.StringUtil.join;
+import static org.mockito.internal.util.reflection.FieldSetter.setField;
+
+/**
+ * This is responsible for serializing a mock, it is enabled if the mock is implementing {@link Serializable}.
+ *
+ * <p>
+ *     The way it works is to enable serialization with mode {@link SerializableMode#ACROSS_CLASSLOADERS},
+ *     if the mock settings is set to be serializable the mock engine will implement the
+ *     {@link CrossClassLoaderSerializableMock} marker interface.
+ *     This interface defines a the {@link CrossClassLoaderSerializableMock#writeReplace()}
+ *     whose signature match the one that is looked by the standard Java serialization.
+ * </p>
+ *
+ * <p>
+ *     Then in the proxy class there will be a generated <code>writeReplace</code> that will delegate to
+ *     {@link ForWriteReplace#doWriteReplace(MockAccess)} of mockito, and in turn will delegate to the custom
+ *     implementation of this class {@link #writeReplace(Object)}. This method has a specific
+ *     knowledge on how to serialize a mockito mock that is based on ByteBuddy and will ignore other Mockito MockMakers.
+ * </p>
+ *
+ * <p><strong>Only one instance per mock! See {@link MockMethodInterceptor}</strong></p>
+ *
+ * TODO check the class is mockable in the deserialization side
+ *
+ * @see SubclassByteBuddyMockMaker
+ * @see org.mockito.internal.creation.bytebuddy.MockMethodInterceptor
+ * @author Brice Dutheil
+ * @since 1.10.0
+ */
+@Incubating
+class ByteBuddyCrossClassLoaderSerializationSupport implements Serializable {
+    private static final long serialVersionUID = 7411152578314420778L;
+    private static final String MOCKITO_PROXY_MARKER = "ByteBuddyMockitoProxyMarker";
+    private boolean instanceLocalCurrentlySerializingFlag = false;
+    private final Lock mutex = new ReentrantLock();
+
+    /**
+     * Custom implementation of the <code>writeReplace</code> method for serialization.
+     * <p/>
+     * Here's how it's working and why :
+     * <ol>
+     *
+     *     <li>
+     *         <p>When first entering in this method, it's because some is serializing the mock, with some code like :</p>
+     *
+     * <pre class="code"><code class="java">
+     * objectOutputStream.writeObject(mock);
+     * </code></pre>
+     *
+     *         <p>So, {@link ObjectOutputStream} will track the <code>writeReplace</code> method in the instance and
+     *         execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock.
+     *         At this point, the code will return an
+     *         {@link CrossClassLoaderSerializableMock}.</p>
+     *     </li>
+     *     <li>
+     *         <p>Now, in the constructor
+     *         {@link CrossClassLoaderSerializationProxy#CrossClassLoaderSerializationProxy(java.lang.Object)}
+     *         the mock is being serialized in a custom way (using {@link MockitoMockObjectOutputStream}) to a
+     *         byte array. So basically it means the code is performing double nested serialization of the passed
+     *         <code>mockitoMock</code>.</p>
+     *
+     *         <p>However the <code>ObjectOutputStream</code> will still detect the custom
+     *         <code>writeReplace</code> and execute it.
+     *         <em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)}
+     *         doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the
+     *         written stream, <strong><code>writeReplace</code> is always called by
+     *         <code>ObjectOutputStream</code></strong>.)</em></p>
+     *
+     *         <p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using
+     *         a flag that marks the mock as already being replaced, and then shouldn't replace itself again.
+     *         <strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs
+     *         to be protected against concurrent access, hence the reentrant lock.</p>
+     *     </li>
+     * </ol>
+     *
+     * @param mockitoMock The Mockito mock to be serialized.
+     * @return A wrapper ({@link CrossClassLoaderSerializationProxy}) to be serialized by the calling ObjectOutputStream.
+     * @throws java.io.ObjectStreamException
+     */
+    public Object writeReplace(Object mockitoMock) throws ObjectStreamException {
+        // reentrant lock for critical section. could it be improved ?
+        mutex.lock();
+        try {
+            // mark started flag // per thread, not per instance
+            // temporary loosy hack to avoid stackoverflow
+            if (mockIsCurrentlyBeingReplaced()) {
+                return mockitoMock;
+            }
+            mockReplacementStarted();
+
+            return new CrossClassLoaderSerializationProxy(mockitoMock);
+        } catch (IOException ioe) {
+            MockName mockName = MockUtil.getMockName(mockitoMock);
+            String mockedType = MockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName();
+            throw new MockitoSerializationIssue(join(
+                    "The mock '" + mockName + "' of type '" + mockedType + "'",
+                    "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :",
+                    "  " + ioe.getMessage()
+            ), ioe);
+        } finally {
+            // unmark
+            mockReplacementCompleted();
+            mutex.unlock();
+        }
+    }
+
+
+    private void mockReplacementCompleted() {
+        instanceLocalCurrentlySerializingFlag = false;
+    }
+
+
+    private void mockReplacementStarted() {
+        instanceLocalCurrentlySerializingFlag = true;
+    }
+
+
+    private boolean mockIsCurrentlyBeingReplaced() {
+        return instanceLocalCurrentlySerializingFlag;
+    }
+
+    /**
+     * This is the serialization proxy that will encapsulate the real mock data as a byte array.
+     * <p/>
+     * <p>When called in the constructor it will serialize the mock in a byte array using a
+     * custom {@link MockitoMockObjectOutputStream} that will annotate the mock class in the stream.
+     * Other information are used in this class in order to facilitate deserialization.
+     * </p>
+     * <p/>
+     * <p>Deserialization of the mock will be performed by the {@link #readResolve()} method via
+     * the custom {@link MockitoMockObjectInputStream} that will be in charge of creating the mock class.</p>
+     */
+    public static class CrossClassLoaderSerializationProxy implements Serializable {
+
+        private static final long serialVersionUID = -7600267929109286514L;
+        private final byte[] serializedMock;
+        private final Class<?> typeToMock;
+        private final Set<Class<?>> extraInterfaces;
+
+        /**
+         * Creates the wrapper that be used in the serialization stream.
+         *
+         * <p>Immediately serializes the Mockito mock using specifically crafted {@link MockitoMockObjectOutputStream},
+         * in a byte array.</p>
+         *
+         * @param mockitoMock The Mockito mock to serialize.
+         * @throws java.io.IOException
+         */
+        public CrossClassLoaderSerializationProxy(Object mockitoMock) throws IOException {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            ObjectOutputStream objectOutputStream = new MockitoMockObjectOutputStream(out);
+
+            objectOutputStream.writeObject(mockitoMock);
+
+            objectOutputStream.close();
+            out.close();
+
+            MockCreationSettings<?> mockSettings = MockUtil.getMockSettings(mockitoMock);
+            this.serializedMock = out.toByteArray();
+            this.typeToMock = mockSettings.getTypeToMock();
+            this.extraInterfaces = mockSettings.getExtraInterfaces();
+        }
+
+        /**
+         * Resolves the proxy to a new deserialized instance of the Mockito mock.
+         * <p/>
+         * <p>Uses the custom crafted {@link MockitoMockObjectInputStream} to deserialize the mock.</p>
+         *
+         * @return A deserialized instance of the Mockito mock.
+         * @throws java.io.ObjectStreamException
+         */
+        private Object readResolve() throws ObjectStreamException {
+            try {
+                ByteArrayInputStream bis = new ByteArrayInputStream(serializedMock);
+                ObjectInputStream objectInputStream = new MockitoMockObjectInputStream(bis, typeToMock, extraInterfaces);
+
+                Object deserializedMock = objectInputStream.readObject();
+
+                bis.close();
+                objectInputStream.close();
+
+                return deserializedMock;
+            } catch (IOException ioe) {
+                throw new MockitoSerializationIssue(join(
+                        "Mockito mock cannot be deserialized to a mock of '" + typeToMock.getCanonicalName() + "'. The error was :",
+                        "  " + ioe.getMessage(),
+                        "If you are unsure what is the reason of this exception, feel free to contact us on the mailing list."
+                ), ioe);
+            } catch (ClassNotFoundException cce) {
+                throw new MockitoSerializationIssue(join(
+                        "A class couldn't be found while deserializing a Mockito mock, you should check your classpath. The error was :",
+                        "  " + cce.getMessage(),
+                        "If you are still unsure what is the reason of this exception, feel free to contact us on the mailing list."
+                ), cce);
+            }
+        }
+    }
+
+
+    /**
+     * Special Mockito aware <code>ObjectInputStream</code> that will resolve the Mockito proxy class.
+     * <p/>
+     * <p>
+     *     This specifically crafted ObjectInoutStream has the most important role to resolve the Mockito generated
+     *     class. It is doing so via the {@link #resolveClass(ObjectStreamClass)} which looks in the stream
+     *     for a Mockito marker. If this marker is found it will try to resolve the mockito class otherwise it
+     *     delegates class resolution to the default super behavior.
+     *     The mirror method used for serializing the mock is {@link MockitoMockObjectOutputStream#annotateClass(Class)}.
+     * </p>
+     * <p/>
+     * <p>
+     *     When this marker is found, {@link ByteBuddyMockMaker#createMockType(MockCreationSettings)} methods are being used
+     *     to create the mock class.
+     * </p>
+     */
+    public static class MockitoMockObjectInputStream extends ObjectInputStream {
+        private final Class<?> typeToMock;
+        private final Set<Class<?>> extraInterfaces;
+
+        public MockitoMockObjectInputStream(InputStream in, Class<?> typeToMock, Set<Class<?>> extraInterfaces) throws IOException {
+            super(in);
+            this.typeToMock = typeToMock;
+            this.extraInterfaces = extraInterfaces;
+            enableResolveObject(true); // ensure resolving is enabled
+        }
+
+        /**
+         * Resolve the Mockito proxy class if it is marked as such.
+         * <p/>
+         * <p>Uses the fields {@link #typeToMock} and {@link #extraInterfaces} to
+         * create the Mockito proxy class as the <code>ObjectStreamClass</code>
+         * doesn't carry useful information for this purpose.</p>
+         *
+         * @param desc Description of the class in the stream, not used.
+         * @return The class that will be used to deserialize the instance mock.
+         * @throws java.io.IOException
+         * @throws ClassNotFoundException
+         */
+        @Override
+        protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+            if (notMarkedAsAMockitoMock(readObject())) {
+                return super.resolveClass(desc);
+            }
+
+            // create the Mockito mock class before it can even be deserialized
+            try {
+                @SuppressWarnings("unchecked")
+                Class<?> proxyClass = ((ClassCreatingMockMaker) Plugins.getMockMaker()).createMockType(
+                        new CreationSettings()
+                                .setTypeToMock(typeToMock)
+                                .setExtraInterfaces(extraInterfaces)
+                                .setSerializableMode(SerializableMode.ACROSS_CLASSLOADERS));
+
+                hackClassNameToMatchNewlyCreatedClass(desc, proxyClass);
+                return proxyClass;
+            } catch (ClassCastException cce) {
+                throw new MockitoSerializationIssue(join(
+                        "A Byte Buddy-generated mock cannot be deserialized into a non-Byte Buddy generated mock class",
+                        "",
+                        "The mock maker in use was: " + Plugins.getMockMaker().getClass()
+                ), cce);
+            }
+        }
+
+        /**
+         * Hack the <code>name</code> field of the given <code>ObjectStreamClass</code> with
+         * the <code>newProxyClass</code>.
+         * <p/>
+         * The parent ObjectInputStream will check the name of the class in the stream matches the name of the one
+         * that is created in this method.
+         * <p/>
+         * The CGLIB classes uses a hash of the classloader and/or maybe some other data that allow them to be
+         * relatively unique in a JVM.
+         * <p/>
+         * When names differ, which happens when the mock is deserialized in another ClassLoader, a
+         * <code>java.io.InvalidObjectException</code> is thrown, so this part of the code is hacking through
+         * the given <code>ObjectStreamClass</code> to change the name with the newly created class.
+         *
+         * @param descInstance The <code>ObjectStreamClass</code> that will be hacked.
+         * @param proxyClass   The proxy class whose name will be applied.
+         * @throws java.io.InvalidObjectException
+         */
+        private void hackClassNameToMatchNewlyCreatedClass(ObjectStreamClass descInstance, Class<?> proxyClass) throws ObjectStreamException {
+            try {
+                Field classNameField = descInstance.getClass().getDeclaredField("name");
+                setField(descInstance, classNameField,proxyClass.getCanonicalName());
+            } catch (NoSuchFieldException nsfe) {
+                throw new MockitoSerializationIssue(join(
+                        "Wow, the class 'ObjectStreamClass' in the JDK don't have the field 'name',",
+                        "this is definitely a bug in our code as it means the JDK team changed a few internal things.",
+                        "",
+                        "Please report an issue with the JDK used, a code sample and a link to download the JDK would be welcome."
+                ), nsfe);
+            }
+        }
+
+        /**
+         * Read the stream class annotation and identify it as a Mockito mock or not.
+         *
+         * @param marker The marker to identify.
+         * @return <code>true</code> if not marked as a Mockito, <code>false</code> if the class annotation marks a Mockito mock.
+         */
+        private boolean notMarkedAsAMockitoMock(Object marker) {
+            return !MOCKITO_PROXY_MARKER.equals(marker);
+        }
+    }
+
+
+    /**
+     * Special Mockito aware <code>ObjectOutputStream</code>.
+     * <p/>
+     * <p>
+     * This output stream has the role of marking in the stream the Mockito class. This
+     * marking process is necessary to identify the proxy class that will need to be recreated.
+     * <p/>
+     * The mirror method used for deserializing the mock is
+     * {@link MockitoMockObjectInputStream#resolveClass(ObjectStreamClass)}.
+     * </p>
+     */
+    private static class MockitoMockObjectOutputStream extends ObjectOutputStream {
+        private static final String NOTHING = "";
+
+        public MockitoMockObjectOutputStream(ByteArrayOutputStream out) throws IOException {
+            super(out);
+        }
+
+        /**
+         * Annotates (marks) the class if this class is a Mockito mock.
+         *
+         * @param cl The class to annotate.
+         * @throws java.io.IOException
+         */
+        @Override
+        protected void annotateClass(Class<?> cl) throws IOException {
+            writeObject(mockitoProxyClassMarker(cl));
+            // might be also useful later, for embedding classloader info ...maybe ...maybe not
+        }
+
+        /**
+         * Returns the Mockito marker if this class is a Mockito mock.
+         *
+         * @param cl The class to mark.
+         * @return The marker if this is a Mockito proxy class, otherwise returns a void marker.
+         */
+        private String mockitoProxyClassMarker(Class<?> cl) {
+            if (CrossClassLoaderSerializableMock.class.isAssignableFrom(cl)) {
+                return MOCKITO_PROXY_MARKER;
+            } else {
+                return NOTHING;
+            }
+        }
+    }
+
+
+    /**
+     * Simple interface that hold a correct <code>writeReplace</code> signature that can be seen by an
+     * <code>ObjectOutputStream</code>.
+     * <p/>
+     * It will be applied before the creation of the mock when the mock setting says it should serializable.
+     */
+    public interface CrossClassLoaderSerializableMock {
+        Object writeReplace();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMaker.java b/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMaker.java
new file mode 100644
index 0000000..07d638b
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMaker.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import org.mockito.Incubating;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+
+/**
+ * ByteBuddy MockMaker.
+ *
+ * This class will serve as the programmatic entry point to all mockito internal MockMakers.
+ * Currently the default and only mock maker is the subclassing engine, but with enough feedback we can later
+ * promote the inlining engine for features like final class/methods mocks.
+ *
+ * The programmatic API could look like {@code mock(Final.class, withSettings().finalClasses())}.
+ */
+public class ByteBuddyMockMaker implements ClassCreatingMockMaker {
+    private ClassCreatingMockMaker defaultByteBuddyMockMaker = new SubclassByteBuddyMockMaker();
+
+    @Override
+    public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+        return defaultByteBuddyMockMaker.createMock(settings, handler);
+    }
+
+    @Override
+    public <T> Class<? extends T> createMockType(MockCreationSettings<T> creationSettings) {
+        return defaultByteBuddyMockMaker.createMockType(creationSettings);
+    }
+
+    @Override
+    public MockHandler getHandler(Object mock) {
+        return defaultByteBuddyMockMaker.getHandler(mock);
+    }
+
+    @Override
+    public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+        defaultByteBuddyMockMaker.resetMock(mock, newHandler, settings);
+    }
+
+    @Override
+    @Incubating
+    public TypeMockability isTypeMockable(Class<?> type) {
+        return defaultByteBuddyMockMaker.isTypeMockable(type);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/BytecodeGenerator.java b/src/main/java/org/mockito/internal/creation/bytebuddy/BytecodeGenerator.java
new file mode 100644
index 0000000..a131c04
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/BytecodeGenerator.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+public interface BytecodeGenerator {
+
+    <T> Class<? extends T> mockClass(MockFeatures<T> features);
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/ClassCreatingMockMaker.java b/src/main/java/org/mockito/internal/creation/bytebuddy/ClassCreatingMockMaker.java
new file mode 100644
index 0000000..b6f9b3f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/ClassCreatingMockMaker.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+
+interface ClassCreatingMockMaker extends MockMaker {
+    <T> Class<? extends T> createMockType(MockCreationSettings<T> settings);
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java b/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java
new file mode 100644
index 0000000..a986295
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.agent.ByteBuddyAgent;
+import org.mockito.Incubating;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.base.MockitoInitializationException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.internal.creation.instance.Instantiator;
+import org.mockito.internal.util.Platform;
+import org.mockito.internal.util.concurrent.WeakConcurrentMap;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Modifier;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+
+import static org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.EXCLUDES;
+import static org.mockito.internal.util.StringUtil.join;
+
+/**
+ * Agent and subclass based mock maker.
+ * <p>
+ * This mock maker which uses a combination of the Java instrumentation API and sub-classing rather than creating
+ * a new sub-class to create a mock. This way, it becomes possible to mock final types and methods. This mock
+ * maker <strong>must to be activated explicitly</strong> for supporting mocking final types and methods:
+ * <p>
+ * <p>
+ * This mock maker can be activated by creating the file <code>/mockito-extensions/org.mockito.plugins.MockMaker</code>
+ * containing the text <code>mock-maker-inline</code> or <code>org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker</code>.
+ * <p>
+ * <p>
+ * This mock maker will make a best effort to avoid subclass creation when creating a mock. Otherwise it will use the
+ * <code>org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker</code> to create the mock class. That means
+ * that the following condition is true
+ * <p>
+ * <pre class="code"><code class="java">
+ * class Foo { }
+ * assert mock(Foo.class).getClass() == Foo.class;
+ * </pre></code>
+ * <p>
+ * unless any of the following conditions is met, in such case the mock maker <em>fall backs</em> to the
+ * the creation of a subclass.
+ * <p>
+ * <ul>
+ * <li>the type to mock is an abstract class.</li>
+ * <li>the mock is set to require additional interfaces.</li>
+ * <li>the mock is <a href="#20">explicitly set to support serialization</a>.</li>
+ * </ul>
+ * <p>
+ * <p>
+ * Some type of the JDK cannot be mocked, this includes <code>Class</code>, <code>String</code>, and wrapper types.
+ * <p>
+ * <p>
+ * Nevertheless, final methods of such types are mocked when using the inlining mock maker. Mocking final types and enums
+ * does however remain impossible when explicitly requiring serialization support or when adding ancillary interfaces.
+ * <p>
+ * <p>
+ * Important behavioral changes when using inline-mocks:
+ * <ul>
+ * <li>Mockito is capable of mocking package-private methods even if they are defined in different packages than
+ * the mocked type. Mockito voluntarily never mocks package-visible methods within <code>java.*</code> packages.</li>
+ * <li>Additionally to final types, Mockito can now mock types that are not visible for extension; such types
+ * include private types in a protected package.</li>
+ * <li>Mockito can no longer mock <code>native</code> methods. Inline mocks require byte code manipulation of a
+ * method where native methods do not offer any byte code to manipulate.</li>
+ * <li>Mockito cannot longer strip <code>synchronized</code> modifiers from mocked instances.</li>
+ * </ul>
+ * <p>
+ * <p>
+ * Note that inline mocks require a Java agent to be attached. Mockito will attempt an attachment of a Java agent upon
+ * loading the mock maker for creating inline mocks. Such runtime attachment is only possible when using a JVM that
+ * is part of a JDK or when using a Java 9 VM. When running on a non-JDK VM prior to Java 9, it is however possible to
+ * manually add the <a href="http://bytebuddy.net">Byte Buddy Java agent jar</a> using the <code>-javaagent</code>
+ * parameter upon starting the JVM. Furthermore, the inlining mock maker requires the VM to support class retransformation
+ * (also known as HotSwap). All major VM distributions such as HotSpot (OpenJDK), J9 (IBM/Websphere) or Zing (Azul)
+ * support this feature.
+ */
+@Incubating
+public class InlineByteBuddyMockMaker implements ClassCreatingMockMaker {
+
+    private static final Instrumentation INSTRUMENTATION;
+
+    private static final Throwable INITIALIZATION_ERROR;
+
+    static {
+        Instrumentation instrumentation;
+        Throwable initializationError = null;
+        try {
+            try {
+                instrumentation = ByteBuddyAgent.install();
+                if (!instrumentation.isRetransformClassesSupported()) {
+                    throw new IllegalStateException(join(
+                            "Byte Buddy requires retransformation for creating inline mocks. This feature is unavailable on the current VM.",
+                            "",
+                            "You cannot use this mock maker on this VM"));
+                }
+                File boot = File.createTempFile("mockitoboot", ".jar");
+                boot.deleteOnExit();
+                JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(boot));
+                try {
+                    String source = "org/mockito/internal/creation/bytebuddy/MockMethodDispatcher";
+                    InputStream inputStream = InlineByteBuddyMockMaker.class.getClassLoader().getResourceAsStream(source + ".raw");
+                    if (inputStream == null) {
+                        throw new IllegalStateException(join(
+                                "The MockMethodDispatcher class file is not locatable: " + source + ".raw",
+                                "",
+                                "The class loader responsible for looking up the resource: " + InlineByteBuddyMockMaker.class.getClassLoader()
+                        ));
+                    }
+                    outputStream.putNextEntry(new JarEntry(source + ".class"));
+                    try {
+                        int length;
+                        byte[] buffer = new byte[1024];
+                        while ((length = inputStream.read(buffer)) != -1) {
+                            outputStream.write(buffer, 0, length);
+                        }
+                    } finally {
+                        inputStream.close();
+                    }
+                    outputStream.closeEntry();
+                } finally {
+                    outputStream.close();
+                }
+                instrumentation.appendToBootstrapClassLoaderSearch(new JarFile(boot));
+                try {
+                    Class<?> dispatcher = Class.forName("org.mockito.internal.creation.bytebuddy.MockMethodDispatcher");
+                    if (dispatcher.getClassLoader() != null) {
+                        throw new IllegalStateException(join(
+                                "The MockMethodDispatcher must not be loaded manually but must be injected into the bootstrap class loader.",
+                                "",
+                                "The dispatcher class was already loaded by: " + dispatcher.getClassLoader()));
+                    }
+                } catch (ClassNotFoundException cnfe) {
+                    throw new IllegalStateException(join(
+                            "Mockito failed to inject the MockMethodDispatcher class into the bootstrap class loader",
+                            "",
+                            "It seems like your current VM does not support the instrumentation API correctly."), cnfe);
+                }
+            } catch (IOException ioe) {
+                throw new IllegalStateException(join(
+                        "Mockito could not self-attach a Java agent to the current VM. This feature is required for inline mocking.",
+                        "This error occured due to an I/O error during the creation of this agent: " + ioe,
+                        "",
+                        "Potentially, the current VM does not support the instrumentation API correctly"), ioe);
+            }
+        } catch (Throwable throwable) {
+            instrumentation = null;
+            initializationError = throwable;
+        }
+        INSTRUMENTATION = instrumentation;
+        INITIALIZATION_ERROR = initializationError;
+    }
+
+    private final BytecodeGenerator bytecodeGenerator;
+
+    private final WeakConcurrentMap<Object, MockMethodInterceptor> mocks = new WeakConcurrentMap.WithInlinedExpunction<Object, MockMethodInterceptor>();
+
+    public InlineByteBuddyMockMaker() {
+        if (INITIALIZATION_ERROR != null) {
+            throw new MockitoInitializationException(join(
+                    "Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)",
+                    "",
+                    Platform.describe()), INITIALIZATION_ERROR);
+        }
+        bytecodeGenerator = new TypeCachingBytecodeGenerator(new InlineBytecodeGenerator(INSTRUMENTATION, mocks), true);
+    }
+
+    @Override
+    public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+        Class<? extends T> type = createMockType(settings);
+
+        Instantiator instantiator = Plugins.getInstantiatorProvider().getInstantiator(settings);
+        try {
+            T instance = instantiator.newInstance(type);
+            MockMethodInterceptor mockMethodInterceptor = new MockMethodInterceptor(asInternalMockHandler(handler), settings);
+            mocks.put(instance, mockMethodInterceptor);
+            if (instance instanceof MockAccess) {
+                ((MockAccess) instance).setMockitoInterceptor(mockMethodInterceptor);
+            }
+            return instance;
+        } catch (org.mockito.internal.creation.instance.InstantiationException e) {
+            throw new MockitoException("Unable to create mock instance of type '" + type.getSimpleName() + "'", e);
+        }
+    }
+
+    @Override
+    public <T> Class<? extends T> createMockType(MockCreationSettings<T> settings) {
+        try {
+            return bytecodeGenerator.mockClass(MockFeatures.withMockFeatures(
+                    settings.getTypeToMock(),
+                    settings.getExtraInterfaces(),
+                    settings.getSerializableMode()
+            ));
+        } catch (Exception bytecodeGenerationFailed) {
+            throw prettifyFailure(settings, bytecodeGenerationFailed);
+        }
+    }
+
+    private <T> RuntimeException prettifyFailure(MockCreationSettings<T> mockFeatures, Exception generationFailed) {
+        if (mockFeatures.getTypeToMock().isArray()) {
+            throw new MockitoException(join(
+                    "Arrays cannot be mocked: " + mockFeatures.getTypeToMock() + ".",
+                    ""
+            ), generationFailed);
+        }
+        if (Modifier.isFinal(mockFeatures.getTypeToMock().getModifiers())) {
+            throw new MockitoException(join(
+                    "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",
+                    "Can not mock final classes with the following settings :",
+                    " - explicit serialization (e.g. withSettings().serializable())",
+                    " - extra interfaces (e.g. withSettings().extraInterfaces(...))",
+                    "",
+                    "You are seeing this disclaimer because Mockito is configured to create inlined mocks.",
+                    "You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.",
+                    "",
+                    "Underlying exception : " + generationFailed
+            ), generationFailed);
+        }
+        if (Modifier.isPrivate(mockFeatures.getTypeToMock().getModifiers())) {
+            throw new MockitoException(join(
+                    "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",
+                    "Most likely it is a private class that is not visible by Mockito",
+                    "",
+                    "You are seeing this disclaimer because Mockito is configured to create inlined mocks.",
+                    "You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.",
+                    ""
+            ), generationFailed);
+        }
+        throw new MockitoException(join(
+                "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",
+                "",
+                "If you're not sure why you're getting this error, please report to the mailing list.",
+                "",
+                Platform.warnForVM(
+                        "IBM J9 VM", "Early IBM virtual machine are known to have issues with Mockito, please upgrade to an up-to-date version.\n",
+                        "Hotspot", Platform.isJava8BelowUpdate45() ? "Java 8 early builds have bugs that were addressed in Java 1.8.0_45, please update your JDK!\n" : ""
+                ),
+                Platform.describe(),
+                "",
+                "You are seeing this disclaimer because Mockito is configured to create inlined mocks.",
+                "You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.",
+                "",
+                "Underlying exception : " + generationFailed
+        ), generationFailed);
+    }
+
+
+    private static InternalMockHandler<?> asInternalMockHandler(MockHandler handler) {
+        if (!(handler instanceof InternalMockHandler)) {
+            throw new MockitoException(join(
+                    "At the moment you cannot provide own implementations of MockHandler.",
+                    "Please refer to the javadocs for the MockMaker interface.",
+                    ""
+            ));
+        }
+        return (InternalMockHandler<?>) handler;
+    }
+
+    @Override
+    public MockHandler getHandler(Object mock) {
+        MockMethodInterceptor interceptor = mocks.get(mock);
+        if (interceptor == null) {
+            return null;
+        } else {
+            return interceptor.handler;
+        }
+    }
+
+    @Override
+    public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+        MockMethodInterceptor mockMethodInterceptor = new MockMethodInterceptor(asInternalMockHandler(newHandler), settings);
+        mocks.put(mock, mockMethodInterceptor);
+        if (mock instanceof MockAccess) {
+            ((MockAccess) mock).setMockitoInterceptor(mockMethodInterceptor);
+        }
+    }
+
+    @Override
+    public TypeMockability isTypeMockable(final Class<?> type) {
+        return new TypeMockability() {
+            @Override
+            public boolean mockable() {
+                return INSTRUMENTATION.isModifiableClass(type) && !EXCLUDES.contains(type);
+            }
+
+            @Override
+            public String nonMockableReason() {
+                if (mockable()) {
+                    return "";
+                }
+                if (type.isPrimitive()) {
+                    return "primitive type";
+                }
+                if (EXCLUDES.contains(type)) {
+                    return "Cannot mock wrapper types, String.class or Class.class";
+                }
+                return "VM does not not support modification of given type";
+            }
+        };
+    }
+
+    static Throwable hideRecursiveCall(Throwable throwable, int current, Class<?> targetType) {
+        try {
+            StackTraceElement[] stack = throwable.getStackTrace();
+            int skip = 0;
+            StackTraceElement next;
+            do {
+                next = stack[stack.length - current - ++skip];
+            } while (!next.getClassName().equals(targetType.getName()));
+            int top = stack.length - current - skip;
+            StackTraceElement[] cleared = new StackTraceElement[stack.length - skip];
+            System.arraycopy(stack, 0, cleared, 0, top);
+            System.arraycopy(stack, top + skip, cleared, top, current);
+            throwable.setStackTrace(cleared);
+            return throwable;
+        } catch (RuntimeException ignored) {
+            // This should not happen unless someone instrumented or manipulated exception stack traces.
+            return throwable;
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/InlineBytecodeGenerator.java b/src/main/java/org/mockito/internal/creation/bytebuddy/InlineBytecodeGenerator.java
new file mode 100644
index 0000000..da0d527
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/InlineBytecodeGenerator.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.ClassFileVersion;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.asm.AsmVisitorWrapper;
+import net.bytebuddy.description.field.FieldDescription;
+import net.bytebuddy.description.field.FieldList;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.method.MethodList;
+import net.bytebuddy.description.method.ParameterDescription;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.dynamic.ClassFileLocator;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.implementation.Implementation;
+import net.bytebuddy.jar.asm.ClassVisitor;
+import net.bytebuddy.jar.asm.MethodVisitor;
+import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.matcher.ElementMatchers;
+import net.bytebuddy.pool.TypePool;
+import net.bytebuddy.utility.RandomString;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.concurrent.WeakConcurrentMap;
+import org.mockito.internal.util.concurrent.WeakConcurrentSet;
+import org.mockito.mock.SerializableMode;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.lang.reflect.Modifier;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import static net.bytebuddy.implementation.MethodDelegation.to;
+import static net.bytebuddy.implementation.MethodDelegation.withDefaultConfiguration;
+import static net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue.OfConstant.of;
+import static net.bytebuddy.matcher.ElementMatchers.*;
+
+public class InlineBytecodeGenerator implements BytecodeGenerator, ClassFileTransformer {
+
+    @SuppressWarnings("unchecked")
+    static final Set<Class<?>> EXCLUDES = new HashSet<Class<?>>(Arrays.asList(Class.class,
+            Boolean.class,
+            Byte.class,
+            Short.class,
+            Character.class,
+            Integer.class,
+            Long.class,
+            Float.class,
+            Double.class,
+            String.class));
+
+    private final Instrumentation instrumentation;
+
+    private final ByteBuddy byteBuddy;
+
+    private final WeakConcurrentSet<Class<?>> mocked;
+
+    private final String identifier;
+
+    private final MockMethodAdvice advice;
+
+    private final BytecodeGenerator subclassEngine;
+
+    public InlineBytecodeGenerator(Instrumentation instrumentation, WeakConcurrentMap<Object, MockMethodInterceptor> mocks) {
+        this.instrumentation = instrumentation;
+        byteBuddy = new ByteBuddy()
+                .with(TypeValidation.DISABLED)
+                .with(Implementation.Context.Disabled.Factory.INSTANCE);
+        mocked = new WeakConcurrentSet<Class<?>>(WeakConcurrentSet.Cleaner.INLINE);
+        identifier = RandomString.make();
+        advice = new MockMethodAdvice(mocks, identifier);
+        subclassEngine = new TypeCachingBytecodeGenerator(new SubclassBytecodeGenerator(withDefaultConfiguration()
+                .withBinders(of(MockMethodAdvice.Identifier.class, identifier))
+                .to(MockMethodAdvice.ForReadObject.class), isAbstract().or(isNative())), false);
+        MockMethodDispatcher.set(identifier, advice);
+        instrumentation.addTransformer(this, true);
+    }
+
+    @Override
+    public <T> Class<? extends T> mockClass(MockFeatures<T> features) {
+        boolean subclassingRequired = !features.interfaces.isEmpty()
+                || features.serializableMode != SerializableMode.NONE
+                || Modifier.isAbstract(features.mockedType.getModifiers());
+
+        checkSupportedCombination(subclassingRequired, features);
+
+        synchronized (this) {
+            triggerRetransformation(features);
+        }
+
+        return subclassingRequired ?
+                subclassEngine.mockClass(features) :
+                features.mockedType;
+    }
+
+    private <T> void triggerRetransformation(MockFeatures<T> features) {
+        Set<Class<?>> types = new HashSet<Class<?>>();
+        Class<?> type = features.mockedType;
+        do {
+            if (mocked.add(type)) {
+                types.add(type);
+                addInterfaces(types, type.getInterfaces());
+            }
+            type = type.getSuperclass();
+        } while (type != null);
+        if (!types.isEmpty()) {
+            try {
+                instrumentation.retransformClasses(types.toArray(new Class<?>[types.size()]));
+            } catch (UnmodifiableClassException exception) {
+                for (Class<?> failed : types) {
+                    mocked.remove(failed);
+                }
+                throw new MockitoException("Could not modify all classes " + types, exception);
+            }
+        }
+    }
+
+    private <T> void checkSupportedCombination(boolean subclassingRequired, MockFeatures<T> features) {
+        if (subclassingRequired
+                && !features.mockedType.isArray()
+                && !features.mockedType.isPrimitive()
+                && Modifier.isFinal(features.mockedType.getModifiers())) {
+            throw new MockitoException("Unsupported settings with this type '" + features.mockedType.getName() + "'");
+        }
+    }
+
+    private void addInterfaces(Set<Class<?>> types, Class<?>[] interfaces) {
+        for (Class<?> type : interfaces) {
+            if (mocked.add(type)) {
+                types.add(type);
+                addInterfaces(types, type.getInterfaces());
+            }
+        }
+    }
+
+    @Override
+    public byte[] transform(ClassLoader loader,
+                            String className,
+                            Class<?> classBeingRedefined,
+                            ProtectionDomain protectionDomain,
+                            byte[] classfileBuffer) throws IllegalClassFormatException {
+        if (classBeingRedefined == null
+                || !mocked.contains(classBeingRedefined)
+                || EXCLUDES.contains(classBeingRedefined)) {
+            return null;
+        } else {
+            try {
+                return byteBuddy.redefine(classBeingRedefined, ClassFileLocator.Simple.of(classBeingRedefined.getName(), classfileBuffer))
+                        // Note: The VM erases parameter meta data from the provided class file (bug). We just add this information manually.
+                        .visit(new ParameterWritingVisitorWrapper(classBeingRedefined))
+                        .visit(Advice.withCustomMapping()
+                                .bind(MockMethodAdvice.Identifier.class, identifier)
+                                .to(MockMethodAdvice.class).on(isVirtual()
+                                        .and(not(isBridge().or(isHashCode()).or(isEquals()).or(isDefaultFinalizer())))
+                                        .and(not(isDeclaredBy(nameStartsWith("java.")).<MethodDescription>and(isPackagePrivate())))))
+                        .visit(Advice.withCustomMapping()
+                                .bind(MockMethodAdvice.Identifier.class, identifier)
+                                .to(MockMethodAdvice.ForHashCode.class).on(isHashCode()))
+                        .visit(Advice.withCustomMapping()
+                                .bind(MockMethodAdvice.Identifier.class, identifier)
+                                .to(MockMethodAdvice.ForEquals.class).on(isEquals()))
+                        .make()
+                        .getBytes();
+            } catch (Throwable throwable) {
+                return null;
+            }
+        }
+    }
+
+    private static class ParameterWritingVisitorWrapper extends AsmVisitorWrapper.AbstractBase {
+
+        private final Class<?> type;
+
+        private ParameterWritingVisitorWrapper(Class<?> type) {
+            this.type = type;
+        }
+
+        @Override
+        public ClassVisitor wrap(TypeDescription instrumentedType,
+                                 ClassVisitor classVisitor,
+                                 Implementation.Context implementationContext,
+                                 TypePool typePool,
+                                 FieldList<FieldDescription.InDefinedShape> fields,
+                                 MethodList<?> methods,
+                                 int writerFlags,
+                                 int readerFlags) {
+            return implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V8)
+                    ? new ParameterAddingClassVisitor(classVisitor, new TypeDescription.ForLoadedType(type))
+                    : classVisitor;
+        }
+
+        private static class ParameterAddingClassVisitor extends ClassVisitor {
+
+            private final TypeDescription typeDescription;
+
+            private ParameterAddingClassVisitor(ClassVisitor cv, TypeDescription typeDescription) {
+                super(Opcodes.ASM5, cv);
+                this.typeDescription = typeDescription;
+            }
+
+            @Override
+            public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+                MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
+                MethodList<?> methodList = typeDescription.getDeclaredMethods().filter((name.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME)
+                        ? isConstructor()
+                        : ElementMatchers.<MethodDescription>named(name)).and(hasDescriptor(desc)));
+                if (methodList.size() == 1 && methodList.getOnly().getParameters().hasExplicitMetaData()) {
+                    for (ParameterDescription parameterDescription : methodList.getOnly().getParameters()) {
+                        methodVisitor.visitParameter(parameterDescription.getName(), parameterDescription.getModifiers());
+                    }
+                    return new MethodParameterStrippingMethodVisitor(methodVisitor);
+                } else {
+                    return methodVisitor;
+                }
+            }
+        }
+
+        private static class MethodParameterStrippingMethodVisitor extends MethodVisitor {
+
+            public MethodParameterStrippingMethodVisitor(MethodVisitor mv) {
+                super(Opcodes.ASM5, mv);
+            }
+
+            @Override
+            public void visitParameter(String name, int access) {
+                // suppress to avoid additional writing of the parameter if retained.
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/InterceptedInvocation.java b/src/main/java/org/mockito/internal/creation/bytebuddy/InterceptedInvocation.java
new file mode 100644
index 0000000..9ad0247
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/InterceptedInvocation.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.exceptions.VerificationAwareInvocation;
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+import org.mockito.internal.invocation.ArgumentsProcessor;
+import org.mockito.internal.invocation.MockitoMethod;
+import org.mockito.internal.reporting.PrintSettings;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+import org.mockito.invocation.StubInfo;
+
+import static org.mockito.internal.exceptions.Reporter.cannotCallAbstractRealMethod;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+
+class InterceptedInvocation implements Invocation, VerificationAwareInvocation {
+
+    private static final long serialVersionUID = 475027563923510472L;
+
+    private final Object mock;
+    private final MockitoMethod mockitoMethod;
+    private final Object[] arguments, rawArguments;
+    private final SuperMethod superMethod;
+
+    private final int sequenceNumber;
+
+    private final Location location;
+
+    private boolean verified;
+    private boolean isIgnoredForVerification;
+    private StubInfo stubInfo;
+
+    public InterceptedInvocation(Object mock,
+                                 MockitoMethod mockitoMethod,
+                                 Object[] arguments,
+                                 SuperMethod superMethod,
+                                 int sequenceNumber) {
+        this.mock = mock;
+        this.mockitoMethod = mockitoMethod;
+        this.arguments = ArgumentsProcessor.expandVarArgs(mockitoMethod.isVarArgs(), arguments);
+        this.rawArguments = arguments;
+        this.superMethod = superMethod;
+        this.sequenceNumber = sequenceNumber;
+        location = new LocationImpl();
+    }
+
+    @Override
+    public boolean isVerified() {
+        return verified || isIgnoredForVerification;
+    }
+
+    @Override
+    public int getSequenceNumber() {
+        return sequenceNumber;
+    }
+
+    @Override
+    public Location getLocation() {
+        return location;
+    }
+
+    @Override
+    public Object[] getRawArguments() {
+        return rawArguments;
+    }
+
+    @Override
+    public Class<?> getRawReturnType() {
+        return mockitoMethod.getReturnType();
+    }
+
+    @Override
+    public void markVerified() {
+        verified = true;
+    }
+
+    @Override
+    public StubInfo stubInfo() {
+        return stubInfo;
+    }
+
+    @Override
+    public void markStubbed(StubInfo stubInfo) {
+        this.stubInfo = stubInfo;
+    }
+
+    @Override
+    public boolean isIgnoredForVerification() {
+        return isIgnoredForVerification;
+    }
+
+    @Override
+    public void ignoreForVerification() {
+        isIgnoredForVerification = true;
+    }
+
+    @Override
+    public Object getMock() {
+        return mock;
+    }
+
+    @Override
+    public Method getMethod() {
+        return mockitoMethod.getJavaMethod();
+    }
+
+    @Override
+    public Object[] getArguments() {
+        return arguments;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T getArgument(int index) {
+        return (T) arguments[index];
+    }
+
+    @Override
+    public Object callRealMethod() throws Throwable {
+        if (!superMethod.isInvokable()) {
+            throw cannotCallAbstractRealMethod();
+        }
+        return superMethod.invoke();
+    }
+
+    @Override
+    public int hashCode() {
+        //TODO SF we need to provide hash code implementation so that there are no unexpected, slight perf issues
+        return 1;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !o.getClass().equals(this.getClass())) {
+            return false;
+        }
+        InterceptedInvocation other = (InterceptedInvocation) o;
+        return this.mock.equals(other.mock)
+                && this.mockitoMethod.equals(other.mockitoMethod)
+                && this.equalArguments(other.arguments);
+    }
+
+    private boolean equalArguments(Object[] arguments) {
+        return Arrays.equals(arguments, this.arguments);
+    }
+
+    public String toString() {
+        return new PrintSettings().print(ArgumentsProcessor.argumentsToMatchers(getArguments()), this);
+    }
+
+
+    public interface SuperMethod extends Serializable {
+
+        enum IsIllegal implements SuperMethod {
+
+            INSTANCE;
+
+            @Override
+            public boolean isInvokable() {
+                return false;
+            }
+
+            @Override
+            public Object invoke() {
+                throw new IllegalStateException();
+            }
+        }
+
+        class FromCallable implements SuperMethod {
+
+            private static final long serialVersionUID = 47957363950483625L;
+
+            private final Callable<?> callable;
+
+            public FromCallable(Callable<?> callable) {
+                this.callable = callable;
+            }
+
+            @Override
+            public boolean isInvokable() {
+                return true;
+            }
+
+            @Override
+            public Object invoke() throws Throwable {
+                try {
+                    return callable.call();
+                } catch (Throwable t) {
+                    new ConditionalStackTraceFilter().filter(t);
+                    throw t;
+                }
+            }
+        }
+
+        boolean isInvokable();
+
+        Object invoke() throws Throwable;
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/MockAccess.java b/src/main/java/org/mockito/internal/creation/bytebuddy/MockAccess.java
new file mode 100644
index 0000000..35698d8
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/MockAccess.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+public interface MockAccess {
+
+    MockMethodInterceptor getMockitoInterceptor();
+
+    void setMockitoInterceptor(MockMethodInterceptor mockMethodInterceptor);
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/MockFeatures.java b/src/main/java/org/mockito/internal/creation/bytebuddy/MockFeatures.java
new file mode 100644
index 0000000..c92a1b8
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/MockFeatures.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import org.mockito.mock.SerializableMode;
+
+import java.util.Collections;
+import java.util.Set;
+
+class MockFeatures<T> {
+    final Class<T> mockedType;
+    final Set<Class<?>> interfaces;
+    final SerializableMode serializableMode;
+
+    private MockFeatures(Class<T> mockedType, Set<Class<?>> interfaces, SerializableMode serializableMode) {
+        this.mockedType = mockedType;
+        this.interfaces = Collections.unmodifiableSet(interfaces);
+        this.serializableMode = serializableMode;
+    }
+
+    public static <T> MockFeatures<T> withMockFeatures(Class<T> mockedType, Set<Class<?>> interfaces, SerializableMode serializableMode) {
+        return new MockFeatures<T>(mockedType, interfaces, serializableMode);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodAdvice.java b/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodAdvice.java
new file mode 100644
index 0000000..394bd2d
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodAdvice.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.implementation.bind.annotation.Argument;
+import net.bytebuddy.implementation.bind.annotation.This;
+import net.bytebuddy.implementation.bytecode.assign.Assigner;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+import org.mockito.internal.invocation.SerializableMethod;
+import org.mockito.internal.util.concurrent.WeakConcurrentMap;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.concurrent.Callable;
+
+import static org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.hideRecursiveCall;
+
+public class MockMethodAdvice extends MockMethodDispatcher {
+
+    final WeakConcurrentMap<Object, MockMethodInterceptor> interceptors;
+
+    private final String identifier;
+
+    private final SelfCallInfo selfCallInfo = new SelfCallInfo();
+
+    public MockMethodAdvice(WeakConcurrentMap<Object, MockMethodInterceptor> interceptors, String identifier) {
+        this.interceptors = interceptors;
+        this.identifier = identifier;
+    }
+
+    @SuppressWarnings("unused")
+    @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
+    private static Callable<?> enter(@Identifier String identifier,
+                                     @Advice.This Object mock,
+                                     @Advice.Origin Method origin,
+                                     @Advice.AllArguments Object[] arguments) throws Throwable {
+        MockMethodDispatcher dispatcher = MockMethodDispatcher.get(identifier, mock);
+        if (dispatcher == null || !dispatcher.isMocked(mock) || !dispatcher.isOverridden(mock, origin)) {
+            return null;
+        } else {
+            return dispatcher.handle(mock, origin, arguments);
+        }
+    }
+
+    @SuppressWarnings({"unused", "UnusedAssignment"})
+    @Advice.OnMethodExit
+    private static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object returned,
+                             @Advice.Enter Callable<?> mocked) throws Throwable {
+        if (mocked != null) {
+            returned = mocked.call();
+        }
+    }
+
+    @Override
+    public Callable<?> handle(Object instance, Method origin, Object[] arguments) throws Throwable {
+        MockMethodInterceptor interceptor = interceptors.get(instance);
+        if (interceptor == null) {
+            return null;
+        }
+        InterceptedInvocation.SuperMethod superMethod;
+        if (instance instanceof Serializable) {
+            superMethod = new SerializableSuperMethodCall(identifier, origin, instance, arguments);
+        } else {
+            superMethod = new SuperMethodCall(selfCallInfo, origin, instance, arguments);
+        }
+        return new ReturnValueWrapper(interceptor.doIntercept(instance,
+                origin,
+                arguments,
+                superMethod));
+    }
+
+    @Override
+    public boolean isMock(Object instance) {
+        return interceptors.containsKey(instance);
+    }
+
+    @Override
+    public boolean isMocked(Object instance) {
+        return selfCallInfo.checkSuperCall(instance) && isMock(instance);
+    }
+
+    @Override
+    public boolean isOverridden(Object instance, Method origin) {
+        Class<?> currentType = instance.getClass();
+        do {
+            try {
+                return origin.equals(currentType.getDeclaredMethod(origin.getName(), origin.getParameterTypes()));
+            } catch (NoSuchMethodException ignored) {
+                currentType = currentType.getSuperclass();
+            }
+        } while (currentType != null);
+        return true;
+    }
+
+    private static class SuperMethodCall implements InterceptedInvocation.SuperMethod {
+
+        private final SelfCallInfo selfCallInfo;
+
+        private final Method origin;
+
+        private final Object instance;
+
+        private final Object[] arguments;
+
+        private SuperMethodCall(SelfCallInfo selfCallInfo, Method origin, Object instance, Object[] arguments) {
+            this.selfCallInfo = selfCallInfo;
+            this.origin = origin;
+            this.instance = instance;
+            this.arguments = arguments;
+        }
+
+        @Override
+        public boolean isInvokable() {
+            return true;
+        }
+
+        @Override
+        public Object invoke() throws Throwable {
+            if (!Modifier.isPublic(origin.getDeclaringClass().getModifiers() & origin.getModifiers())) {
+                origin.setAccessible(true);
+            }
+            selfCallInfo.set(instance);
+            return tryInvoke(origin, instance, arguments);
+        }
+
+    }
+
+    private static class SerializableSuperMethodCall implements InterceptedInvocation.SuperMethod {
+
+        private final String identifier;
+
+        private final SerializableMethod origin;
+
+        private final Object instance;
+
+        private final Object[] arguments;
+
+        private SerializableSuperMethodCall(String identifier, Method origin, Object instance, Object[] arguments) {
+            this.origin = new SerializableMethod(origin);
+            this.identifier = identifier;
+            this.instance = instance;
+            this.arguments = arguments;
+        }
+
+        @Override
+        public boolean isInvokable() {
+            return true;
+        }
+
+        @Override
+        public Object invoke() throws Throwable {
+            Method method = origin.getJavaMethod();
+            if (!Modifier.isPublic(method.getDeclaringClass().getModifiers() & method.getModifiers())) {
+                method.setAccessible(true);
+            }
+            MockMethodDispatcher mockMethodDispatcher = MockMethodDispatcher.get(identifier, instance);
+            if (!(mockMethodDispatcher instanceof MockMethodAdvice)) {
+                throw new MockitoException("Unexpected dispatcher for advice-based super call");
+            }
+            ((MockMethodAdvice) mockMethodDispatcher).selfCallInfo.set(instance);
+            return tryInvoke(method, instance, arguments);
+        }
+    }
+
+    private static Object tryInvoke(Method origin, Object instance, Object[] arguments) throws Throwable {
+        try {
+            return origin.invoke(instance, arguments);
+        } catch (InvocationTargetException exception) {
+            Throwable cause = exception.getCause();
+            new ConditionalStackTraceFilter().filter(hideRecursiveCall(cause, new Throwable().getStackTrace().length, origin.getDeclaringClass()));
+            throw cause;
+        }
+    }
+
+    private static class ReturnValueWrapper implements Callable<Object> {
+
+        private final Object returned;
+
+        private ReturnValueWrapper(Object returned) {
+            this.returned = returned;
+        }
+
+        @Override
+        public Object call() {
+            return returned;
+        }
+    }
+
+    private static class SelfCallInfo extends ThreadLocal<Object> {
+
+        boolean checkSuperCall(Object value) {
+            Object current = get();
+            if (current == value) {
+                set(null);
+                return false;
+            } else {
+                return true;
+            }
+        }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Identifier {
+
+    }
+
+    static class ForHashCode {
+
+        @SuppressWarnings("unused")
+        @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
+        private static boolean enter(@Identifier String id,
+                                     @Advice.This Object self) {
+            MockMethodDispatcher dispatcher = MockMethodDispatcher.get(id, self);
+            return dispatcher != null && dispatcher.isMock(self);
+        }
+
+        @SuppressWarnings({"unused", "UnusedAssignment"})
+        @Advice.OnMethodExit
+        private static void enter(@Advice.This Object self,
+                                  @Advice.Return(readOnly = false) int hashCode,
+                                  @Advice.Enter boolean skipped) {
+            if (skipped) {
+                hashCode = System.identityHashCode(self);
+            }
+        }
+    }
+
+    static class ForEquals {
+
+        @SuppressWarnings("unused")
+        @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
+        private static boolean enter(@Identifier String identifier,
+                                     @Advice.This Object self) {
+            MockMethodDispatcher dispatcher = MockMethodDispatcher.get(identifier, self);
+            return dispatcher != null && dispatcher.isMock(self);
+        }
+
+        @SuppressWarnings({"unused", "UnusedAssignment"})
+        @Advice.OnMethodExit
+        private static void enter(@Advice.This Object self,
+                                  @Advice.Argument(0) Object other,
+                                  @Advice.Return(readOnly = false) boolean equals,
+                                  @Advice.Enter boolean skipped) {
+            if (skipped) {
+                equals = self == other;
+            }
+        }
+    }
+
+    public static class ForReadObject {
+
+        @SuppressWarnings("unused")
+        public static void doReadObject(@Identifier String identifier,
+                                        @This MockAccess thiz,
+                                        @Argument(0) ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
+            objectInputStream.defaultReadObject();
+            MockMethodAdvice mockMethodAdvice = (MockMethodAdvice) MockMethodDispatcher.get(identifier, thiz);
+            if (mockMethodAdvice != null) {
+                mockMethodAdvice.interceptors.put(thiz, thiz.getMockitoInterceptor());
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodDispatcher.java b/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodDispatcher.java
new file mode 100644
index 0000000..1bf4cce
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodDispatcher.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public abstract class MockMethodDispatcher {
+
+    private static final ConcurrentMap<String, MockMethodDispatcher> INSTANCE = new ConcurrentHashMap<String, MockMethodDispatcher>();
+
+    public static MockMethodDispatcher get(String identifier, Object mock) {
+        if (mock == INSTANCE) { // Avoid endless loop if ConcurrentHashMap was redefined to check for being a mock.
+            return null;
+        } else {
+            return INSTANCE.get(identifier);
+        }
+    }
+
+    public static void set(String identifier, MockMethodDispatcher dispatcher) {
+        INSTANCE.putIfAbsent(identifier, dispatcher);
+    }
+
+    public abstract Callable<?> handle(Object instance, Method origin, Object[] arguments) throws Throwable;
+
+    public abstract boolean isMock(Object instance);
+
+    public abstract boolean isMocked(Object instance);
+
+    public abstract boolean isOverridden(Object instance, Method origin);
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodInterceptor.java b/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodInterceptor.java
new file mode 100644
index 0000000..804d700
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodInterceptor.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.implementation.bind.annotation.*;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.invocation.MockitoMethod;
+import org.mockito.internal.invocation.SerializableMethod;
+import org.mockito.internal.progress.SequenceNumber;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+public class MockMethodInterceptor implements Serializable {
+
+    private static final long serialVersionUID = 7152947254057253027L;
+
+    final InternalMockHandler handler;
+
+    private final MockCreationSettings mockCreationSettings;
+
+    private final ByteBuddyCrossClassLoaderSerializationSupport serializationSupport;
+
+    public MockMethodInterceptor(InternalMockHandler handler, MockCreationSettings mockCreationSettings) {
+        this.handler = handler;
+        this.mockCreationSettings = mockCreationSettings;
+        serializationSupport = new ByteBuddyCrossClassLoaderSerializationSupport();
+    }
+
+    Object doIntercept(Object mock,
+                       Method invokedMethod,
+                       Object[] arguments,
+                       InterceptedInvocation.SuperMethod superMethod) throws Throwable {
+        return handler.handle(new InterceptedInvocation(
+                mock,
+                createMockitoMethod(invokedMethod),
+                arguments,
+                superMethod,
+                SequenceNumber.next()
+        ));
+    }
+
+    private MockitoMethod createMockitoMethod(Method method) {
+        if (mockCreationSettings.isSerializable()) {
+            return new SerializableMethod(method);
+        } else {
+            return new DelegatingMethod(method);
+        }
+    }
+
+    public MockHandler getMockHandler() {
+        return handler;
+    }
+
+    public ByteBuddyCrossClassLoaderSerializationSupport getSerializationSupport() {
+        return serializationSupport;
+    }
+
+    public static class ForHashCode {
+
+        @SuppressWarnings("unused")
+        public static int doIdentityHashCode(@This Object thiz) {
+            return System.identityHashCode(thiz);
+        }
+    }
+
+    public static class ForEquals {
+
+        @SuppressWarnings("unused")
+        public static boolean doIdentityEquals(@This Object thiz, @Argument(0) Object other) {
+            return thiz == other;
+        }
+    }
+
+    public static class ForWriteReplace {
+
+        public static Object doWriteReplace(@This MockAccess thiz) throws ObjectStreamException {
+            return thiz.getMockitoInterceptor().getSerializationSupport().writeReplace(thiz);
+        }
+    }
+
+    public static class DispatcherDefaultingToRealMethod {
+
+        @SuppressWarnings("unused")
+        @RuntimeType
+        @BindingPriority(BindingPriority.DEFAULT * 2)
+        public static Object interceptSuperCallable(@This Object mock,
+                                                    @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor,
+                                                    @Origin Method invokedMethod,
+                                                    @AllArguments Object[] arguments,
+                                                    @SuperCall(serializableProxy = true) Callable<?> superCall) throws Throwable {
+            if (interceptor == null) {
+                return superCall.call();
+            }
+            return interceptor.doIntercept(
+                    mock,
+                    invokedMethod,
+                    arguments,
+                    new InterceptedInvocation.SuperMethod.FromCallable(superCall)
+            );
+        }
+
+        @SuppressWarnings("unused")
+        @RuntimeType
+        public static Object interceptAbstract(@This Object mock,
+                                               @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor,
+                                               @StubValue Object stubValue,
+                                               @Origin Method invokedMethod,
+                                               @AllArguments Object[] arguments) throws Throwable {
+            if (interceptor == null) {
+                return stubValue;
+            }
+            return interceptor.doIntercept(
+                    mock,
+                    invokedMethod,
+                    arguments,
+                    InterceptedInvocation.SuperMethod.IsIllegal.INSTANCE
+            );
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMaker.java b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMaker.java
new file mode 100644
index 0000000..91a4245
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMaker.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import java.lang.reflect.Modifier;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.internal.creation.instance.Instantiator;
+import org.mockito.internal.util.Platform;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+
+import static org.mockito.internal.util.StringUtil.join;
+
+/**
+ * Subclass based mock maker.
+ *
+ * This mock maker tries to create a subclass to represent a mock. It uses the given mock settings, that contains
+ * the type to mock, extra interfaces, and serialization support.
+ *
+ * <p>
+ * The type to mock has to be not final and not part of the JDK. THe created mock will implement extra interfaces
+ * if any. And will implement <code>Serializable</code> if this settings is explicitly set.
+ */
+public class SubclassByteBuddyMockMaker implements ClassCreatingMockMaker {
+
+    private final BytecodeGenerator cachingMockBytecodeGenerator;
+
+    public SubclassByteBuddyMockMaker() {
+        this(new SubclassInjectionLoader());
+    }
+
+    public SubclassByteBuddyMockMaker(SubclassLoader loader) {
+        cachingMockBytecodeGenerator = new TypeCachingBytecodeGenerator(new SubclassBytecodeGenerator(loader), false);
+    }
+
+    @Override
+    public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+        Class<? extends T> mockedProxyType = createMockType(settings);
+
+        Instantiator instantiator = Plugins.getInstantiatorProvider().getInstantiator(settings);
+        T mockInstance = null;
+        try {
+            mockInstance = instantiator.newInstance(mockedProxyType);
+            MockAccess mockAccess = (MockAccess) mockInstance;
+            mockAccess.setMockitoInterceptor(new MockMethodInterceptor(asInternalMockHandler(handler), settings));
+
+            return ensureMockIsAssignableToMockedType(settings, mockInstance);
+        } catch (ClassCastException cce) {
+            throw new MockitoException(join(
+                    "ClassCastException occurred while creating the mockito mock :",
+                    "  class to mock : " + describeClass(settings.getTypeToMock()),
+                    "  created class : " + describeClass(mockedProxyType),
+                    "  proxy instance class : " + describeClass(mockInstance),
+                    "  instance creation by : " + instantiator.getClass().getSimpleName(),
+                    "",
+                    "You might experience classloading issues, please ask the mockito mailing-list.",
+                    ""
+            ), cce);
+        } catch (org.mockito.internal.creation.instance.InstantiationException e) {
+            throw new MockitoException("Unable to create mock instance of type '" + mockedProxyType.getSuperclass().getSimpleName() + "'", e);
+        }
+    }
+
+    @Override
+    public <T> Class<? extends T> createMockType(MockCreationSettings<T> settings) {
+        try {
+            return cachingMockBytecodeGenerator.mockClass(MockFeatures.withMockFeatures(
+                    settings.getTypeToMock(),
+                    settings.getExtraInterfaces(),
+                    settings.getSerializableMode()
+            ));
+        } catch (Exception bytecodeGenerationFailed) {
+            throw prettifyFailure(settings, bytecodeGenerationFailed);
+        }
+    }
+
+    private static <T> T ensureMockIsAssignableToMockedType(MockCreationSettings<T> settings, T mock) {
+        // Force explicit cast to mocked type here, instead of
+        // relying on the JVM to implicitly cast on the client call site.
+        // This allows us to catch earlier the ClassCastException earlier
+        Class<T> typeToMock = settings.getTypeToMock();
+        return typeToMock.cast(mock);
+    }
+
+    private <T> RuntimeException prettifyFailure(MockCreationSettings<T> mockFeatures, Exception generationFailed) {
+        if (mockFeatures.getTypeToMock().isArray()) {
+            throw new MockitoException(join(
+                    "Mockito cannot mock arrays: " + mockFeatures.getTypeToMock() + ".",
+                    ""
+                    ), generationFailed);
+        }
+        if (Modifier.isPrivate(mockFeatures.getTypeToMock().getModifiers())) {
+            throw new MockitoException(join(
+                    "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",
+                    "Most likely it is due to mocking a private class that is not visible to Mockito",
+                    ""
+            ), generationFailed);
+        }
+        throw new MockitoException(join(
+                "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",
+                "",
+                "Mockito can only mock non-private & non-final classes.",
+                "If you're not sure why you're getting this error, please report to the mailing list.",
+                "",
+                Platform.warnForVM(
+                        "IBM J9 VM", "Early IBM virtual machine are known to have issues with Mockito, please upgrade to an up-to-date version.\n",
+                        "Hotspot", Platform.isJava8BelowUpdate45() ? "Java 8 early builds have bugs that were addressed in Java 1.8.0_45, please update your JDK!\n" : ""
+                ),
+                Platform.describe(),
+                "",
+                "Underlying exception : " + generationFailed
+        ), generationFailed);
+    }
+
+    private static String describeClass(Class<?> type) {
+        return type == null ? "null" : "'" + type.getCanonicalName() + "', loaded by classloader : '" + type.getClassLoader() + "'";
+    }
+
+    private static String describeClass(Object instance) {
+        return instance == null ? "null" : describeClass(instance.getClass());
+    }
+
+    @Override
+    public MockHandler getHandler(Object mock) {
+        if (!(mock instanceof MockAccess)) {
+            return null;
+        }
+        return ((MockAccess) mock).getMockitoInterceptor().getMockHandler();
+    }
+
+    @Override
+    public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+        ((MockAccess) mock).setMockitoInterceptor(
+                new MockMethodInterceptor(asInternalMockHandler(newHandler), settings)
+        );
+    }
+
+    @Override
+    public TypeMockability isTypeMockable(final Class<?> type) {
+        return new TypeMockability() {
+            @Override
+            public boolean mockable() {
+                return !type.isPrimitive() && !Modifier.isFinal(type.getModifiers());
+            }
+
+            @Override
+            public String nonMockableReason() {
+                if(mockable()) {
+                    return "";
+                }
+                if (type.isPrimitive()) {
+                    return "primitive type";
+                }
+                if (Modifier.isFinal(type.getModifiers())) {
+                    return "final class";
+                }
+                return join("not handled type");
+            }
+        };
+    }
+
+    private static InternalMockHandler<?> asInternalMockHandler(MockHandler handler) {
+        if (!(handler instanceof InternalMockHandler)) {
+            throw new MockitoException(join(
+                    "At the moment you cannot provide own implementations of MockHandler.",
+                    "Please refer to the javadocs for the MockMaker interface.",
+                    ""
+            ));
+        }
+        return (InternalMockHandler<?>) handler;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java
new file mode 100644
index 0000000..b63e5d0
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.modifier.SynchronizationState;
+import net.bytebuddy.description.modifier.Visibility;
+import net.bytebuddy.dynamic.DynamicType;
+import net.bytebuddy.dynamic.loading.MultipleParentClassLoader;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.implementation.FieldAccessor;
+import net.bytebuddy.implementation.Implementation;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.mockito.internal.creation.bytebuddy.ByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializableMock;
+import org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.DispatcherDefaultingToRealMethod;
+import org.mockito.mock.SerializableMode;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Random;
+
+import static java.lang.Thread.currentThread;
+import static net.bytebuddy.description.modifier.Visibility.PRIVATE;
+import static net.bytebuddy.dynamic.Transformer.ForMethod.withModifiers;
+import static net.bytebuddy.implementation.MethodDelegation.to;
+import static net.bytebuddy.implementation.attribute.MethodAttributeAppender.ForInstrumentedMethod.INCLUDING_RECEIVER;
+import static net.bytebuddy.matcher.ElementMatchers.*;
+
+class SubclassBytecodeGenerator implements BytecodeGenerator {
+
+    private final SubclassLoader loader;
+
+    private final ByteBuddy byteBuddy;
+    private final Random random;
+
+    private final Implementation readReplace;
+    private final ElementMatcher<? super MethodDescription> matcher;
+
+    public SubclassBytecodeGenerator() {
+        this(new SubclassInjectionLoader());
+    }
+
+    public SubclassBytecodeGenerator(SubclassLoader loader) {
+        this(loader, null, any());
+    }
+
+    public SubclassBytecodeGenerator(Implementation readReplace, ElementMatcher<? super MethodDescription> matcher) {
+        this(new SubclassInjectionLoader(), readReplace, matcher);
+    }
+
+    protected SubclassBytecodeGenerator(SubclassLoader loader, Implementation readReplace, ElementMatcher<? super MethodDescription> matcher) {
+        this.loader = loader;
+        this.readReplace = readReplace;
+        this.matcher = matcher;
+        byteBuddy = new ByteBuddy().with(TypeValidation.DISABLED);
+        random = new Random();
+    }
+
+    @Override
+    public <T> Class<? extends T> mockClass(MockFeatures<T> features) {
+        DynamicType.Builder<T> builder =
+                byteBuddy.subclass(features.mockedType)
+                         .name(nameFor(features.mockedType))
+                         .ignoreAlso(isGroovyMethod())
+                         .annotateType(features.mockedType.getAnnotations())
+                         .implement(new ArrayList<Type>(features.interfaces))
+                         .method(matcher)
+                           .intercept(to(DispatcherDefaultingToRealMethod.class))
+                           .transform(withModifiers(SynchronizationState.PLAIN))
+                           .attribute(INCLUDING_RECEIVER)
+                         .method(isHashCode())
+                           .intercept(to(MockMethodInterceptor.ForHashCode.class))
+                         .method(isEquals())
+                           .intercept(to(MockMethodInterceptor.ForEquals.class))
+                         .serialVersionUid(42L)
+                         .defineField("mockitoInterceptor", MockMethodInterceptor.class, PRIVATE)
+                         .implement(MockAccess.class)
+                           .intercept(FieldAccessor.ofBeanProperty());
+        if (features.serializableMode == SerializableMode.ACROSS_CLASSLOADERS) {
+            builder = builder.implement(CrossClassLoaderSerializableMock.class)
+                             .intercept(to(MockMethodInterceptor.ForWriteReplace.class));
+        }
+        if (readReplace != null) {
+            builder = builder.defineMethod("readObject", void.class, Visibility.PRIVATE)
+                    .withParameters(ObjectInputStream.class)
+                    .throwing(ClassNotFoundException.class, IOException.class)
+                    .intercept(readReplace);
+        }
+        return builder.make()
+                      .load(new MultipleParentClassLoader.Builder()
+                              .append(features.mockedType)
+                              .append(features.interfaces)
+                              .append(currentThread().getContextClassLoader())
+                              .append(MockAccess.class, DispatcherDefaultingToRealMethod.class)
+                              .append(MockMethodInterceptor.class,
+                                      MockMethodInterceptor.ForHashCode.class,
+                                      MockMethodInterceptor.ForEquals.class).build(MockMethodInterceptor.class.getClassLoader()),
+                              loader.getStrategy(features.mockedType))
+                      .getLoaded();
+    }
+
+    private static ElementMatcher<MethodDescription> isGroovyMethod() {
+        return isDeclaredBy(named("groovy.lang.GroovyObjectSupport"));
+    }
+
+    // TODO inspect naming strategy (for OSGI, signed package, java.* (and bootstrap classes), etc...)
+    private String nameFor(Class<?> type) {
+        String typeName = type.getName();
+        if (isComingFromJDK(type)
+                || isComingFromSignedJar(type)
+                || isComingFromSealedPackage(type)) {
+            typeName = "codegen." + typeName;
+        }
+        return String.format("%s$%s$%d", typeName, "MockitoMock", Math.abs(random.nextInt()));
+    }
+
+    private boolean isComingFromJDK(Class<?> type) {
+        // Comes from the manifest entry :
+        // Implementation-Title: Java Runtime Environment
+        // This entry is not necessarily present in every jar of the JDK
+        return type.getPackage() != null && "Java Runtime Environment".equalsIgnoreCase(type.getPackage().getImplementationTitle())
+                || type.getName().startsWith("java.")
+                || type.getName().startsWith("javax.");
+    }
+
+    private boolean isComingFromSealedPackage(Class<?> type) {
+        return type.getPackage() != null && type.getPackage().isSealed();
+    }
+
+    private boolean isComingFromSignedJar(Class<?> type) {
+        return type.getSigners() != null;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassInjectionLoader.java b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassInjectionLoader.java
new file mode 100644
index 0000000..510e633
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassInjectionLoader.java
@@ -0,0 +1,11 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+
+class SubclassInjectionLoader implements SubclassLoader {
+
+    @Override
+    public ClassLoadingStrategy<ClassLoader> getStrategy(Class<?> mockedType) {
+        return ClassLoadingStrategy.Default.INJECTION.with(mockedType.getProtectionDomain());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassLoader.java b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassLoader.java
new file mode 100644
index 0000000..9d10de5
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassLoader.java
@@ -0,0 +1,9 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+
+public interface SubclassLoader {
+
+    ClassLoadingStrategy<ClassLoader> getStrategy(Class<?> mockedType);
+
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/TypeCachingBytecodeGenerator.java b/src/main/java/org/mockito/internal/creation/bytebuddy/TypeCachingBytecodeGenerator.java
new file mode 100644
index 0000000..3883400
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/TypeCachingBytecodeGenerator.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.TypeCache;
+import org.mockito.mock.SerializableMode;
+
+import java.lang.ref.ReferenceQueue;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+class TypeCachingBytecodeGenerator extends ReferenceQueue<ClassLoader> implements BytecodeGenerator {
+
+    private final Object BOOTSTRAP_LOCK = new Object();
+
+    private final BytecodeGenerator bytecodeGenerator;
+
+    private final TypeCache<SerializationFeatureKey> typeCache;
+
+    public TypeCachingBytecodeGenerator(BytecodeGenerator bytecodeGenerator, boolean weak) {
+        this.bytecodeGenerator = bytecodeGenerator;
+        typeCache = new TypeCache.WithInlineExpunction<SerializationFeatureKey>(weak ? TypeCache.Sort.WEAK : TypeCache.Sort.SOFT);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> Class<T> mockClass(final MockFeatures<T> params) {
+        try {
+            ClassLoader classLoader = params.mockedType.getClassLoader();
+            return (Class<T>) typeCache.findOrInsert(classLoader,
+                    new SerializationFeatureKey(params.mockedType, params.interfaces, params.serializableMode),
+                    new Callable<Class<?>>() {
+                        @Override
+                        public Class<?> call() throws Exception {
+                            return bytecodeGenerator.mockClass(params);
+                        }
+                    }, classLoader == null ? BOOTSTRAP_LOCK : classLoader);
+        } catch (IllegalArgumentException exception) {
+            Throwable cause = exception.getCause();
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            } else {
+                throw exception;
+            }
+        }
+    }
+
+    private static class SerializationFeatureKey extends TypeCache.SimpleKey {
+
+        private final SerializableMode serializableMode;
+
+        private SerializationFeatureKey(Class<?> type, Set<Class<?>> additionalType, SerializableMode serializableMode) {
+            super(type, additionalType);
+            this.serializableMode = serializableMode;
+        }
+
+        @Override
+        public boolean equals(Object object) {
+            if (this == object) return true;
+            if (object == null || getClass() != object.getClass()) return false;
+            if (!super.equals(object)) return false;
+            SerializationFeatureKey that = (SerializationFeatureKey) object;
+            return serializableMode.equals(that.serializableMode);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = super.hashCode();
+            result = 31 * result + serializableMode.hashCode();
+            return result;
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/package-info.java b/src/main/java/org/mockito/internal/creation/bytebuddy/package-info.java
new file mode 100644
index 0000000..d94013f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * ByteBuddy related stuff.
+ */
+package org.mockito.internal.creation.bytebuddy;
diff --git a/src/main/java/org/mockito/internal/creation/cglib/AcrossJVMSerializationFeature.java b/src/main/java/org/mockito/internal/creation/cglib/AcrossJVMSerializationFeature.java
deleted file mode 100644
index 384f8e6..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/AcrossJVMSerializationFeature.java
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.Incubating;
-import org.mockito.exceptions.base.MockitoSerializationIssue;
-import org.mockito.internal.creation.instance.InstantiatorProvider;
-import org.mockito.internal.creation.settings.CreationSettings;
-import org.mockito.internal.util.MockUtil;
-import org.mockito.internal.util.reflection.FieldSetter;
-import org.mockito.mock.MockCreationSettings;
-import org.mockito.mock.MockName;
-import org.mockito.mock.SerializableMode;
-
-import java.io.*;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Set;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import static org.mockito.internal.util.StringJoiner.join;
-
-/**
- * This is responsible for serializing a mock, it is enabled if the mock is implementing
- * {@link Serializable}.
- *
- * <p>
- *     The way it works is to enable serialization via the {@link #enableSerializationAcrossJVM(MockCreationSettings)},
- *     if the mock settings is set to be serializable it will add the {@link AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable}
- *     interface.
- *     This interface defines a the {@link AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable#writeReplace()}
- *     whose signature match the one that is looked by the standard Java serialization.
- * </p>
- *
- * <p>
- *     Then in the {@link org.mockito.internal.creation.cglib.MethodInterceptorFilter} of mockito, if the <code>writeReplace</code> method is called,
- *     it will use the custom implementation of this class {@link #writeReplace(Object)}. This method has a specific
- *     knowledge on how to serialize a mockito mock that is based on CGLIB.
- * </p>
- *
- * <p><strong>Only one instance per mock! See {@link org.mockito.internal.creation.cglib.MethodInterceptorFilter}</strong></p>
- *
- * TODO use a proper way to add the interface
- * TODO offer a way to disable completely this behavior, or maybe enable this behavior only with a specific setting
- * TODO check the class is mockable in the deserialization side
- *
- * @see org.mockito.internal.creation.cglib.CglibMockMaker
- * @see org.mockito.internal.creation.cglib.MethodInterceptorFilter
- * @author Brice Dutheil
- * @since 1.10.0
- */
-@Incubating
-class AcrossJVMSerializationFeature implements Serializable {
-    private static final long serialVersionUID = 7411152578314420778L;
-    private static final String MOCKITO_PROXY_MARKER = "MockitoProxyMarker";
-    private boolean instanceLocalCurrentlySerializingFlag = false;
-    private final Lock mutex = new ReentrantLock();
-
-    public boolean isWriteReplace(Method method) {
-        return  method.getReturnType() == Object.class
-                && method.getParameterTypes().length == 0
-                && method.getName().equals("writeReplace");
-    }
-
-
-    /**
-     * Custom implementation of the <code>writeReplace</code> method for serialization.
-     *
-     * Here's how it's working and why :
-     * <ol>
-     *     <li>
-     *         <p>When first entering in this method, it's because some is serializing the mock, with some code like :
-     * <pre class="code"><code class="java">
-     *     objectOutputStream.writeObject(mock);
-     * </code></pre>
-     *         So, {@link ObjectOutputStream} will track the <code>writeReplace</code> method in the instance and
-     *         execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock.
-     *         At this point, the code will return an
-     *         {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy}.</p>
-     *     </li>
-     *     <li>
-     *         <p>Now, in the constructor
-     *         {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy#AcrossJVMMockSerializationProxy(Object)}
-     *         the mock is being serialized in a custom way (using
-     *         {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream}) to a
-     *         byte array. So basically it means the code is performing double nested serialization of the passed
-     *         <code>mockitoMock</code>.</p>
-     *
-     *         <p>However the <code>ObjectOutputStream</code> will still detect the custom
-     *         <code>writeReplace</code> and execute it.
-     *         <em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)}
-     *         doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the
-     *         written stream, <strong><code>writeReplace</code> is always called by
-     *         <code>ObjectOutputStream</code></strong>.)</em></p>
-     *
-     *         <p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using
-     *         a flag that marks the mock as already being replaced, and then shouldn't replace itself again.
-     *         <strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs
-     *         to be protected against concurrent access, hence the reentrant lock.</p>
-     *     </li>
-     * </ol>
-     *
-     *
-     * @param mockitoMock The Mockito mock to be serialized.
-     * @return A wrapper ({@link AcrossJVMMockSerializationProxy}) to be serialized by the calling ObjectOutputStream.
-     * @throws ObjectStreamException
-     */
-    public Object writeReplace(Object mockitoMock) throws ObjectStreamException {
-        try {
-            // reentrant lock for critical section. could it be improved ?
-            mutex.lock();
-            // mark started flag // per thread, not per instance
-            // temporary loosy hack to avoid stackoverflow
-            if(mockIsCurrentlyBeingReplaced()) {
-                return mockitoMock;
-            }
-            mockReplacementStarted();
-
-            return new AcrossJVMMockSerializationProxy(mockitoMock);
-        } catch (IOException ioe) {
-            MockUtil mockUtil = new MockUtil();
-            MockName mockName = mockUtil.getMockName(mockitoMock);
-            String mockedType = mockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName();
-            throw new MockitoSerializationIssue(join(
-                    "The mock '" + mockName + "' of type '" + mockedType + "'",
-                    "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :",
-                    "  " + ioe.getMessage()
-            ), ioe);
-        } finally {
-            // unmark
-            mockReplacementCompleted();
-            mutex.unlock();
-        }
-    }
-
-
-    private void mockReplacementCompleted() {
-        instanceLocalCurrentlySerializingFlag = false;
-    }
-
-
-    private void mockReplacementStarted() {
-        instanceLocalCurrentlySerializingFlag = true;
-    }
-
-
-    private boolean mockIsCurrentlyBeingReplaced() {
-        return instanceLocalCurrentlySerializingFlag;
-    }
-
-
-    /**
-     * Enable serialization serialization that will work across classloaders / and JVM.
-     *
-     * <p>Only enable if settings says the mock should be serializable. In this case add the
-     * {@link AcrossJVMMockitoMockSerializable} to the extra interface list.</p>
-     *
-     * @param settings Mock creation settings.
-     * @param <T> Type param to not be bothered by the generics
-     */
-    public <T> void enableSerializationAcrossJVM(MockCreationSettings<T> settings) {
-        if (settings.getSerializableMode() == SerializableMode.ACROSS_CLASSLOADERS) {
-            // havin faith that this set is modifiable
-            // TODO use a proper way to add the interface
-            settings.getExtraInterfaces().add(AcrossJVMMockitoMockSerializable.class);
-        }
-    }
-
-
-    /**
-     * This is the serialization proxy that will encapsulate the real mock data as a byte array.
-     *
-     * <p>When called in the constructor it will serialize the mock in a byte array using a
-     * custom {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream} that
-     * will annotate the mock class in the stream.
-     * Other information are used in this class in order to facilitate deserialization.
-     * </p>
-     *
-     * <p>Deserialization of the mock will be performed by the {@link #readResolve()} method via
-     * the custom {@link MockitoMockObjectInputStream} that will be in charge of creating the mock class.</p>
-     */
-    public static class AcrossJVMMockSerializationProxy implements Serializable {
-
-
-        private static final long serialVersionUID = -7600267929109286514L;
-        private final byte[] serializedMock;
-        private final Class typeToMock;
-        private final Set<Class> extraInterfaces;
-        /**
-         * Creates the wrapper that be used in the serialization stream.
-         *
-         * <p>Immediately serializes the Mockito mock using specifically crafted
-         * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream},
-         * in a byte array.</p>
-         *
-         * @param mockitoMock The Mockito mock to serialize.
-         * @throws IOException
-         */
-        public AcrossJVMMockSerializationProxy(Object mockitoMock) throws IOException {
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            ObjectOutputStream objectOutputStream = new MockitoMockObjectOutputStream(out);
-
-            objectOutputStream.writeObject(mockitoMock);
-
-            objectOutputStream.close();
-            out.close();
-
-            MockCreationSettings mockSettings = new MockUtil().getMockSettings(mockitoMock);
-            this.serializedMock = out.toByteArray();
-            this.typeToMock = mockSettings.getTypeToMock();
-            this.extraInterfaces = mockSettings.getExtraInterfaces();
-        }
-
-        /**
-         * Resolves the proxy to a new deserialized instance of the Mockito mock.
-         *
-         * <p>Uses the custom crafted {@link MockitoMockObjectInputStream} to deserialize the mock.</p>
-         *
-         * @return A deserialized instance of the Mockito mock.
-         * @throws ObjectStreamException
-         */
-        private Object readResolve() throws ObjectStreamException {
-            try {
-                ByteArrayInputStream bis = new ByteArrayInputStream(serializedMock);
-                ObjectInputStream objectInputStream = new MockitoMockObjectInputStream(bis, typeToMock, extraInterfaces);
-
-                Object deserializedMock = objectInputStream.readObject();
-
-                bis.close();
-                objectInputStream.close();
-
-                return deserializedMock;
-            } catch (IOException ioe) {
-                throw new MockitoSerializationIssue(join(
-                        "Mockito mock cannot be deserialized to a mock of '" + typeToMock.getCanonicalName() + "'. The error was :",
-                        "  " + ioe.getMessage(),
-                        "If you are unsure what is the reason of this exception, feel free to contact us on the mailing list."
-                ), ioe);
-            } catch (ClassNotFoundException cce) {
-                throw new MockitoSerializationIssue(join(
-                        "A class couldn't be found while deserializing a Mockito mock, you should check your classpath. The error was :",
-                        "  " + cce.getMessage(),
-                        "If you are still unsure what is the reason of this exception, feel free to contact us on the mailing list."
-                ), cce);
-            }
-        }
-    }
-
-
-    /**
-     * Special Mockito aware <code>ObjectInputStream</code> that will resolve the Mockito proxy class.
-     *
-     * <p>
-     *     This specificaly crafted ObjectInoutStream has the most important role to resolve the Mockito generated
-     *     class. It is doing so via the {@link #resolveClass(java.io.ObjectStreamClass)} which looks in the stream
-     *     for a Mockito marker. If this marker is found it will try to resolve the mockito class otherwise it
-     *     delegates class resolution to the default super behavior.
-     *     The mirror method used for serializing the mock is
-     *     {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream#annotateClass(Class)}.
-     * </p>
-     *
-     * <p>
-     *     When this marker is found, {@link org.mockito.internal.creation.cglib.ClassImposterizer} methods are being used to create the mock class.
-     *     <em>Note that behind the <code>ClassImposterizer</code> there is CGLIB and the
-     *     {@link org.mockito.internal.creation.util.SearchingClassLoader} that will look if this enhanced class has
-     *     already been created in an accessible classloader ; so basically this code trusts the ClassImposterizer
-     *     code.</em>
-     * </p>
-     */
-    public static class MockitoMockObjectInputStream extends ObjectInputStream {
-        private final Class typeToMock;
-        private final Set<Class> extraInterfaces;
-
-        public MockitoMockObjectInputStream(InputStream in, Class typeToMock, Set<Class> extraInterfaces) throws IOException {
-            super(in) ;
-            this.typeToMock = typeToMock;
-            this.extraInterfaces = extraInterfaces;
-            enableResolveObject(true); // ensure resolving is enabled
-        }
-
-        /**
-         * Resolve the Mockito proxy class if it is marked as such.
-         *
-         * <p>Uses the fields {@link #typeToMock} and {@link #extraInterfaces} to
-         * create the Mockito proxy class as the <code>ObjectStreamClass</code>
-         * doesn't carry useful information for this purpose.</p>
-         *
-         * @param desc Description of the class in the stream, not used.
-         * @return The class that will be used to deserialize the instance mock.
-         * @throws IOException
-         * @throws ClassNotFoundException
-         */
-        @Override
-        protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
-            if (notMarkedAsAMockitoMock(readObject())) {
-                return super.resolveClass(desc);
-            }
-
-            // TODO check the class is mockable in the deserialization side
-            // ClassImposterizer.INSTANCE.canImposterise(typeToMock);
-
-            // create the Mockito mock class before it can even be deserialized
-            //TODO SF unify creation of imposterizer, constructor code duplicated, pulling in CreationSettings internal class
-            ClassImposterizer imposterizer = new ClassImposterizer(new InstantiatorProvider().getInstantiator(new CreationSettings()));
-            imposterizer.setConstructorsAccessible(typeToMock, true);
-            Class<?> proxyClass = imposterizer.createProxyClass(
-                    typeToMock,
-                    extraInterfaces.toArray(new Class[extraInterfaces.size()])
-            );
-
-            hackClassNameToMatchNewlyCreatedClass(desc, proxyClass);
-
-            return proxyClass;
-
-        }
-
-        /**
-         * Hack the <code>name</code> field of the given <code>ObjectStreamClass</code> with
-         * the <code>newProxyClass</code>.
-         *
-         * The parent ObjectInputStream will check the name of the class in the stream matches the name of the one
-         * that is created in this method.
-         *
-         * The CGLIB classes uses a hash of the classloader and/or maybe some other data that allow them to be
-         * relatively unique in a JVM.
-         *
-         * When names differ, which happens when the mock is deserialized in another ClassLoader, a
-         * <code>java.io.InvalidObjectException</code> is thrown, so this part of the code is hacking through
-         * the given <code>ObjectStreamClass</code> to change the name with the newly created class.
-         *
-         * @param descInstance The <code>ObjectStreamClass</code> that will be hacked.
-         * @param proxyClass The proxy class whose name will be applied.
-         * @throws InvalidObjectException
-         */
-        private void hackClassNameToMatchNewlyCreatedClass(ObjectStreamClass descInstance, Class<?> proxyClass) throws ObjectStreamException {
-            try {
-              Field classNameField = descInstance.getClass().getDeclaredField("name");
-              new FieldSetter(descInstance, classNameField).set(proxyClass.getCanonicalName());
-            } catch (NoSuchFieldException nsfe) {
-                // TODO use our own mockito mock serialization exception
-                throw new MockitoSerializationIssue(join(
-                        "Wow, the class 'ObjectStreamClass' in the JDK don't have the field 'name',",
-                        "this is definitely a bug in our code as it means the JDK team changed a few internal things.",
-                        "",
-                        "Please report an issue with the JDK used, a code sample and a link to download the JDK would be welcome."
-                ), nsfe);
-            }
-        }
-
-        /**
-         * Read the stream class annotation and identify it as a Mockito mock or not.
-         *
-         * @param marker The marker to identify.
-         * @return <code>true</code> if not marked as a Mockito, <code>false</code> if the class annotation marks a Mockito mock.
-         * @throws IOException
-         * @throws ClassNotFoundException
-         */
-        private boolean notMarkedAsAMockitoMock(Object marker) throws IOException, ClassNotFoundException {
-            return !MOCKITO_PROXY_MARKER.equals(marker);
-        }
-    }
-
-
-    /**
-     * Special Mockito aware <code>ObjectOutputStream</code>.
-     *
-     * <p>
-     *     This output stream has the role of marking in the stream the Mockito class. This
-     *     marking process is necessary to identify the proxy class that will need to be recreated.
-     *
-     *     The mirror method used for deserializing the mock is
-     *     {@link MockitoMockObjectInputStream#resolveClass(ObjectStreamClass)}.
-     * </p>
-     *
-     */
-    private static class MockitoMockObjectOutputStream extends ObjectOutputStream {
-        private static final String NOTHING = "";
-
-        public MockitoMockObjectOutputStream(ByteArrayOutputStream out) throws IOException {
-            super(out);
-        }
-
-        /**
-         * Annotates (marks) the class if this class is a Mockito mock.
-         *
-         * @param cl The class to annotate.
-         * @throws IOException
-         */
-        @Override
-        protected void annotateClass(Class<?> cl) throws IOException {
-            writeObject(mockitoProxyClassMarker(cl));
-            // might be also useful later, for embedding classloader info ...maybe ...maybe not
-        }
-
-        /**
-         * Returns the Mockito marker if this class is a Mockito mock.
-         *
-         * @param cl The class to mark.
-         * @return The marker if this is a Mockito proxy class, otherwise returns a void marker.
-         */
-        private String mockitoProxyClassMarker(Class<?> cl) {
-            if (AcrossJVMMockitoMockSerializable.class.isAssignableFrom(cl)) {
-                return MOCKITO_PROXY_MARKER;
-            } else {
-                return NOTHING;
-            }
-        }
-    }
-
-
-    /**
-     * Simple interface that hold a correct <code>writeReplace</code> signature that can be seen by an
-     * <code>ObjectOutputStream</code>.
-     *
-     * It will be applied before the creation of the mock when the mock setting says it should serializable.
-     *
-     * @see #enableSerializationAcrossJVM(org.mockito.mock.MockCreationSettings)
-     */
-    public interface AcrossJVMMockitoMockSerializable {
-        public Object writeReplace() throws java.io.ObjectStreamException;
-    }
-}
diff --git a/src/main/java/org/mockito/internal/creation/cglib/CGLIBHacker.java b/src/main/java/org/mockito/internal/creation/cglib/CGLIBHacker.java
deleted file mode 100644
index 6d0abde..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/CGLIBHacker.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.creation.cglib;

-

-import org.mockito.cglib.proxy.MethodProxy;

-

-import java.io.Serializable;

-import java.lang.reflect.Field;

-

-class CGLIBHacker {

-

-    public void setMockitoNamingPolicy(MethodProxy methodProxy) {

-        try {

-            Field createInfoField = reflectOnCreateInfo(methodProxy);

-            createInfoField.setAccessible(true);

-            Object createInfo = createInfoField.get(methodProxy);

-            Field namingPolicyField = createInfo.getClass().getDeclaredField("namingPolicy");

-            namingPolicyField.setAccessible(true);

-            if (namingPolicyField.get(createInfo) == null) {

-                namingPolicyField.set(createInfo, MockitoNamingPolicy.INSTANCE);

-            }

-        } catch (Exception e) {

-            throw new RuntimeException(

-                            "Unable to set MockitoNamingPolicy on cglib generator which creates FastClasses", e);

-        }

-    }

-

-    @SuppressWarnings("unchecked")

-    private Field reflectOnCreateInfo(MethodProxy methodProxy) throws SecurityException, NoSuchFieldException {

-

-        Class cglibMethodProxyClass = methodProxy.getClass();

-        // in case methodProxy was extended by user, let's traverse the object

-        // graph to find the cglib methodProxy

-        // with all the fields we would like to change

-        while (cglibMethodProxyClass != MethodProxy.class) {

-            cglibMethodProxyClass = methodProxy.getClass().getSuperclass();

-        }

-        return cglibMethodProxyClass.getDeclaredField("createInfo");

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/CglibMockMaker.java b/src/main/java/org/mockito/internal/creation/cglib/CglibMockMaker.java
deleted file mode 100644
index a7025a9..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/CglibMockMaker.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.cglib.proxy.Callback;
-import org.mockito.cglib.proxy.Factory;
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.InternalMockHandler;
-import org.mockito.internal.creation.instance.InstantiatorProvider;
-import org.mockito.invocation.MockHandler;
-import org.mockito.mock.MockCreationSettings;
-import org.mockito.plugins.MockMaker;
-
-/**
- * A MockMaker that uses cglib to generate mocks on a JVM.
- */
-public class CglibMockMaker implements MockMaker {
-
-    public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
-        InternalMockHandler mockitoHandler = cast(handler);
-        new AcrossJVMSerializationFeature().enableSerializationAcrossJVM(settings);
-        return new ClassImposterizer(new InstantiatorProvider().getInstantiator(settings)).imposterise(
-                new MethodInterceptorFilter(mockitoHandler, settings), settings.getTypeToMock(), settings.getExtraInterfaces());
-    }
-
-    private InternalMockHandler cast(MockHandler handler) {
-        if (!(handler instanceof InternalMockHandler)) {
-            throw new MockitoException("At the moment you cannot provide own implementations of MockHandler." +
-                    "\nPlease see the javadocs for the MockMaker interface.");
-        }
-        return (InternalMockHandler) handler;
-    }
-
-    public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
-        ((Factory) mock).setCallback(0, new MethodInterceptorFilter(cast(newHandler), settings));
-    }
-
-    public MockHandler getHandler(Object mock) {
-        if (!(mock instanceof Factory)) {
-            return null;
-        }
-        Factory factory = (Factory) mock;
-        Callback callback = factory.getCallback(0);
-        if (!(callback instanceof MethodInterceptorFilter)) {
-            return null;
-        }
-        return ((MethodInterceptorFilter) callback).getHandler();
-    }
-}
diff --git a/src/main/java/org/mockito/internal/creation/cglib/ClassImposterizer.java b/src/main/java/org/mockito/internal/creation/cglib/ClassImposterizer.java
deleted file mode 100644
index fb2ad95..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/ClassImposterizer.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.cglib.core.CodeGenerationException;
-import org.mockito.cglib.core.NamingPolicy;
-import org.mockito.cglib.core.Predicate;
-import org.mockito.cglib.proxy.*;
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.creation.instance.InstantationException;
-import org.mockito.internal.creation.instance.Instantiator;
-import org.mockito.internal.creation.util.SearchingClassLoader;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collection;
-import java.util.List;
-
-import static org.mockito.internal.util.StringJoiner.join;
-
-/**
- * Inspired on jMock (thanks jMock guys!!!)
- */
-class ClassImposterizer {
-
-    private final Instantiator instantiator;
-
-    public ClassImposterizer(Instantiator instantiator) {
-        this.instantiator = instantiator;
-    }
-    
-    private static final NamingPolicy NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES = new MockitoNamingPolicy() {
-        @Override
-        public String getClassName(String prefix, String source, Object key, Predicate names) {
-            return "codegen." + super.getClassName(prefix, source, key, names);
-        }
-    };
-    
-    private static final CallbackFilter IGNORE_BRIDGE_METHODS = new CallbackFilter() {
-        public int accept(Method method, List<Method> allMethods) {
-            return method.isBridge() ? 1 : 0;
-        }
-    };
-    
-    public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Collection<Class> ancillaryTypes) {
-        return (T) imposterise(interceptor, mockedType, ancillaryTypes.toArray(new Class[ancillaryTypes.size()]));
-    }
-    
-    public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Class<?>... ancillaryTypes) {
-        Class<Factory> proxyClass = null;
-        Object proxyInstance = null;
-        try {
-            setConstructorsAccessible(mockedType, true);
-            proxyClass = createProxyClass(mockedType, ancillaryTypes);
-            proxyInstance = createProxy(proxyClass, interceptor);
-            return mockedType.cast(proxyInstance);
-        } catch (ClassCastException cce) {
-            throw new MockitoException(join(
-                "ClassCastException occurred while creating the mockito proxy :",
-                "  class to mock : " + describeClass(mockedType),
-                "  created class : " + describeClass(proxyClass),
-                "  proxy instance class : " + describeClass(proxyInstance),
-                "  instance creation by : " + instantiator.getClass().getSimpleName(),
-                "",
-                "You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)"
-            ), cce);
-        } finally {
-            setConstructorsAccessible(mockedType, false);
-        }
-    }
-
-    private static String describeClass(Class type) {
-        return type == null? "null" : "'" + type.getCanonicalName() + "', loaded by classloader : '" + type.getClassLoader() + "'";
-    }
-
-    private static String describeClass(Object instance) {
-        return instance == null? "null" : describeClass(instance.getClass());
-    }
-
-    //TODO this method does not belong here
-    public void setConstructorsAccessible(Class<?> mockedType, boolean accessible) {
-        for (Constructor<?> constructor : mockedType.getDeclaredConstructors()) {
-            constructor.setAccessible(accessible);
-        }
-    }
-    
-    public Class<Factory> createProxyClass(Class<?> mockedType, Class<?>... interfaces) {
-        if (mockedType == Object.class) {
-            mockedType = ClassWithSuperclassToWorkAroundCglibBug.class;
-        }
-        
-        Enhancer enhancer = new Enhancer() {
-            @Override
-            @SuppressWarnings("unchecked")
-            protected void filterConstructors(Class sc, List constructors) {
-                // Don't filter
-            }
-        };
-        Class<?>[] allMockedTypes = prepend(mockedType, interfaces);
-		enhancer.setClassLoader(SearchingClassLoader.combineLoadersOf(allMockedTypes));
-        enhancer.setUseFactory(true);
-        if (mockedType.isInterface()) {
-            enhancer.setSuperclass(Object.class);
-            enhancer.setInterfaces(allMockedTypes);
-        } else {
-            enhancer.setSuperclass(mockedType);
-            enhancer.setInterfaces(interfaces);
-        }
-        enhancer.setCallbackTypes(new Class[]{MethodInterceptor.class, NoOp.class});
-        enhancer.setCallbackFilter(IGNORE_BRIDGE_METHODS);
-        if (mockedType.getSigners() != null) {
-            enhancer.setNamingPolicy(NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES);
-        } else {
-            enhancer.setNamingPolicy(MockitoNamingPolicy.INSTANCE);
-        }
-
-        enhancer.setSerialVersionUID(42L);
-        
-        try {
-            return enhancer.createClass(); 
-        } catch (CodeGenerationException e) {
-            if (Modifier.isPrivate(mockedType.getModifiers())) {
-                throw new MockitoException("\n"
-                        + "Mockito cannot mock this class: " + mockedType 
-                        + ".\n"
-                        + "Most likely it is a private class that is not visible by Mockito");
-            }
-            throw new MockitoException("\n"
-                    + "Mockito cannot mock this class: " + mockedType 
-                    + "\n" 
-                    + "Mockito can only mock visible & non-final classes."
-                    + "\n" 
-                    + "If you're not sure why you're getting this error, please report to the mailing list.", e);
-        }
-    }
-    
-    private Object createProxy(Class<Factory> proxyClass, final MethodInterceptor interceptor) {
-        Factory proxy;
-        try {
-            proxy = instantiator.newInstance(proxyClass);
-        } catch (InstantationException e) {
-            throw new MockitoException("Unable to create mock instance of type '" + proxyClass.getSuperclass().getSimpleName() + "'", e);
-        }
-        proxy.setCallbacks(new Callback[] {interceptor, SerializableNoOp.SERIALIZABLE_INSTANCE });
-        return proxy;
-    }
-    
-    private Class<?>[] prepend(Class<?> first, Class<?>... rest) {
-        Class<?>[] all = new Class<?>[rest.length+1];
-        all[0] = first;
-        System.arraycopy(rest, 0, all, 1, rest.length);
-        return all;
-    }
-    
-    public static class ClassWithSuperclassToWorkAroundCglibBug {}
-    
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/DelegatingMockitoMethodProxy.java b/src/main/java/org/mockito/internal/creation/cglib/DelegatingMockitoMethodProxy.java
deleted file mode 100644
index 9a8e963..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/DelegatingMockitoMethodProxy.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.cglib.proxy.MethodProxy;
-import org.mockito.internal.creation.util.MockitoMethodProxy;
-
-class DelegatingMockitoMethodProxy implements MockitoMethodProxy {
-
-    private final MethodProxy methodProxy;
-
-    public DelegatingMockitoMethodProxy(MethodProxy methodProxy) {
-        this.methodProxy = methodProxy;
-    }
-
-    public Object invokeSuper(Object target, Object[] arguments) throws Throwable {
-        return methodProxy.invokeSuper(target, arguments);
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/MethodInterceptorFilter.java b/src/main/java/org/mockito/internal/creation/cglib/MethodInterceptorFilter.java
deleted file mode 100644
index bcb2c19..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/MethodInterceptorFilter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.cglib.proxy.MethodInterceptor;
-import org.mockito.cglib.proxy.MethodProxy;
-import org.mockito.internal.InternalMockHandler;
-import org.mockito.internal.creation.DelegatingMethod;
-import org.mockito.internal.creation.util.MockitoMethodProxy;
-import org.mockito.internal.invocation.InvocationImpl;
-import org.mockito.internal.invocation.MockitoMethod;
-import org.mockito.internal.invocation.SerializableMethod;
-import org.mockito.internal.invocation.realmethod.CleanTraceRealMethod;
-import org.mockito.internal.progress.SequenceNumber;
-import org.mockito.internal.util.ObjectMethodsGuru;
-import org.mockito.invocation.Invocation;
-import org.mockito.invocation.MockHandler;
-import org.mockito.mock.MockCreationSettings;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-
-/**
- * Should be one instance per mock instance, see CglibMockMaker.
- */
-class MethodInterceptorFilter implements MethodInterceptor, Serializable {
-
-    private static final long serialVersionUID = 6182795666612683784L;
-    private final InternalMockHandler handler;
-    final ObjectMethodsGuru objectMethodsGuru = new ObjectMethodsGuru();
-    private final MockCreationSettings mockSettings;
-    private final AcrossJVMSerializationFeature acrossJVMSerializationFeature = new AcrossJVMSerializationFeature();
-
-    public MethodInterceptorFilter(InternalMockHandler handler, MockCreationSettings mockSettings) {
-        this.handler = handler;
-        this.mockSettings = mockSettings;
-    }
-
-    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
-            throws Throwable {
-        if (objectMethodsGuru.isEqualsMethod(method)) {
-            return proxy == args[0];
-        } else if (objectMethodsGuru.isHashCodeMethod(method)) {
-            return hashCodeForMock(proxy);
-        } else if (acrossJVMSerializationFeature.isWriteReplace(method)) {
-            return acrossJVMSerializationFeature.writeReplace(proxy);
-        }
-        
-        MockitoMethodProxy mockitoMethodProxy = createMockitoMethodProxy(methodProxy);
-        new CGLIBHacker().setMockitoNamingPolicy(methodProxy);
-        
-        MockitoMethod mockitoMethod = createMockitoMethod(method);
-        
-        CleanTraceRealMethod realMethod = new CleanTraceRealMethod(mockitoMethodProxy);
-        Invocation invocation = new InvocationImpl(proxy, mockitoMethod, args, SequenceNumber.next(), realMethod);
-        return handler.handle(invocation);
-    }
-   
-    public MockHandler getHandler() {
-        return handler;
-    }
-
-    private int hashCodeForMock(Object mock) {
-        return System.identityHashCode(mock);
-    }
-
-    public MockitoMethodProxy createMockitoMethodProxy(MethodProxy methodProxy) {
-        if (mockSettings.isSerializable())
-            return new SerializableMockitoMethodProxy(methodProxy);
-        return new DelegatingMockitoMethodProxy(methodProxy);
-    }
-    
-    public MockitoMethod createMockitoMethod(Method method) {
-        if (mockSettings.isSerializable()) {
-            return new SerializableMethod(method);
-        } else {
-            return new DelegatingMethod(method);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/MockitoNamingPolicy.java b/src/main/java/org/mockito/internal/creation/cglib/MockitoNamingPolicy.java
deleted file mode 100644
index 3ec390c..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/MockitoNamingPolicy.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.creation.cglib;

-

-import org.mockito.cglib.core.DefaultNamingPolicy;

-

-class MockitoNamingPolicy extends DefaultNamingPolicy {

-    

-    public static final MockitoNamingPolicy INSTANCE = new MockitoNamingPolicy(); 

-    

-    @Override

-    protected String getTag() {

-        return "ByMockitoWithCGLIB";

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/SerializableMockitoMethodProxy.java b/src/main/java/org/mockito/internal/creation/cglib/SerializableMockitoMethodProxy.java
deleted file mode 100644
index 7542294..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/SerializableMockitoMethodProxy.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.cglib.proxy.MethodProxy;
-import org.mockito.internal.creation.util.MockitoMethodProxy;
-import org.mockito.internal.util.reflection.Whitebox;
-
-import java.io.Serializable;
-
-class SerializableMockitoMethodProxy implements MockitoMethodProxy, Serializable {
-
-    private static final long serialVersionUID = -5337859962876770632L;
-    private final Class<?> c1;
-    private final Class<?> c2;
-    private final String desc;
-    private final String name;
-    private final String superName;
-    transient MethodProxy methodProxy;
-
-    public SerializableMockitoMethodProxy(MethodProxy methodProxy) {
-        assert methodProxy != null;
-        Object info = Whitebox.getInternalState(methodProxy, "createInfo");
-        c1 = (Class<?>) Whitebox.getInternalState(info, "c1");
-        c2 = (Class<?>) Whitebox.getInternalState(info, "c2");
-        desc = methodProxy.getSignature().getDescriptor();
-        name = methodProxy.getSignature().getName();
-        superName = methodProxy.getSuperName();
-        this.methodProxy = methodProxy;
-    }
-
-    private MethodProxy getMethodProxy() {
-        if (methodProxy == null) {
-            methodProxy = MethodProxy.create(c1, c2, desc, name, superName);
-        }
-        return methodProxy;
-    }
-
-    public Object invokeSuper(Object target, Object[] arguments) throws Throwable {
-        return getMethodProxy().invokeSuper(target, arguments);
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/SerializableNoOp.java b/src/main/java/org/mockito/internal/creation/cglib/SerializableNoOp.java
deleted file mode 100644
index 807a6eb..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/SerializableNoOp.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.creation.cglib;
-
-import org.mockito.cglib.proxy.Callback;
-import org.mockito.cglib.proxy.NoOp;
-
-import java.io.Serializable;
-
-/**
- * Offer a Serializable implementation of the NoOp CGLIB callback.
- */
-class SerializableNoOp implements NoOp, Serializable {
-
-    private static final long serialVersionUID = 7434976328690189159L;
-    public static final Callback SERIALIZABLE_INSTANCE = new SerializableNoOp();
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/cglib/package.html b/src/main/java/org/mockito/internal/creation/cglib/package.html
deleted file mode 100644
index d195d54..0000000
--- a/src/main/java/org/mockito/internal/creation/cglib/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>CGLIB related stuff</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/instance/ConstructorInstantiator.java b/src/main/java/org/mockito/internal/creation/instance/ConstructorInstantiator.java
index 1832ad3..049d1b8 100644
--- a/src/main/java/org/mockito/internal/creation/instance/ConstructorInstantiator.java
+++ b/src/main/java/org/mockito/internal/creation/instance/ConstructorInstantiator.java
@@ -1,6 +1,13 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.creation.instance;
 
 import java.lang.reflect.Constructor;
+import org.mockito.internal.util.reflection.AccessibilityChanger;
+
+import static org.mockito.internal.util.StringUtil.join;
 
 public class ConstructorInstantiator implements Instantiator {
 
@@ -19,23 +26,39 @@
 
     private static <T> T withParams(Class<T> cls, Object... params) {
         try {
-            //this is kind of overengineered because we don't need to support more params
+            //this is kind of over-engineered because we don't need to support more params
             //however, I know we will be needing it :)
             for (Constructor<?> constructor : cls.getDeclaredConstructors()) {
                 Class<?>[] types = constructor.getParameterTypes();
                 if (paramsMatch(types, params)) {
-                    return (T) constructor.newInstance(params);
+                    return invokeConstructor(constructor, params);
                 }
             }
         } catch (Exception e) {
             throw paramsException(cls, e);
         }
-        throw paramsException(cls, null);
+        throw noMatchingConstructor(cls);
     }
 
-    private static <T> InstantationException paramsException(Class<T> cls, Exception e) {
-        return new InstantationException("Unable to create instance of '"
-                + cls.getSimpleName() + "'.\nPlease ensure that the outer instance has correct type and that the target class has 0-arg constructor.", e);
+    @SuppressWarnings("unchecked")
+    private static <T> T invokeConstructor(Constructor<?> constructor, Object... params) throws java.lang.InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException {
+        AccessibilityChanger accessibility = new AccessibilityChanger();
+        accessibility.enableAccess(constructor);
+        return (T) constructor.newInstance(params);
+    }
+
+    private static <T> InstantiationException paramsException(Class<T> cls, Exception cause) {
+        return new InstantiationException(
+                join("Unable to create instance of '" + cls.getSimpleName() + "'.",
+                     "Please ensure that the outer instance has correct type and that the target class has 0-arg constructor."),
+                cause);
+    }
+
+    private static <T> InstantiationException noMatchingConstructor(Class<T> cls) {
+        return new InstantiationException(
+                join("Unable to create instance of '" + cls.getSimpleName() + "'.",
+                     "Unable to find a matching 1-arg constructor for the outer instance.")
+                , null);
     }
 
     private static boolean paramsMatch(Class<?>[] types, Object[] params) {
@@ -52,10 +75,12 @@
 
     private static <T> T noArgConstructor(Class<T> cls) {
         try {
-            return cls.newInstance();
+            return invokeConstructor(cls.getDeclaredConstructor());
         } catch (Throwable t) {
-            throw new InstantationException("Unable to create instance of '"
-                    + cls.getSimpleName() + "'.\nPlease ensure it has 0-arg constructor which invokes cleanly.", t);
+            throw new InstantiationException(join(
+                    "Unable to create instance of '" + cls.getSimpleName() + "'.",
+                    "Please ensure it has 0-arg constructor which invokes cleanly."),
+                                             t);
         }
     }
 }
diff --git a/src/main/java/org/mockito/internal/creation/instance/DefaultInstantiatorProvider.java b/src/main/java/org/mockito/internal/creation/instance/DefaultInstantiatorProvider.java
new file mode 100644
index 0000000..fe44b6f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/instance/DefaultInstantiatorProvider.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.instance;
+
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.InstantiatorProvider;
+
+public class DefaultInstantiatorProvider implements InstantiatorProvider {
+
+    private final static Instantiator INSTANCE = new ObjenesisInstantiator();
+
+    public Instantiator getInstantiator(MockCreationSettings<?> settings) {
+        if (settings != null && settings.isUsingConstructor()) {
+            return new ConstructorInstantiator(settings.getOuterClassInstance());
+        } else {
+            return INSTANCE;
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/instance/InstantationException.java b/src/main/java/org/mockito/internal/creation/instance/InstantationException.java
deleted file mode 100644
index 751f999..0000000
--- a/src/main/java/org/mockito/internal/creation/instance/InstantationException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.mockito.internal.creation.instance;
-
-import org.mockito.exceptions.base.MockitoException;
-
-public class InstantationException extends MockitoException {
-
-    public InstantationException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/src/main/java/org/mockito/internal/creation/instance/InstantiationException.java b/src/main/java/org/mockito/internal/creation/instance/InstantiationException.java
new file mode 100644
index 0000000..c0151f1
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/instance/InstantiationException.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.instance;
+
+import org.mockito.exceptions.base.MockitoException;
+
+public class InstantiationException extends MockitoException {
+
+    public InstantiationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/creation/instance/Instantiator.java b/src/main/java/org/mockito/internal/creation/instance/Instantiator.java
index ecb788d..b1ee67d 100644
--- a/src/main/java/org/mockito/internal/creation/instance/Instantiator.java
+++ b/src/main/java/org/mockito/internal/creation/instance/Instantiator.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.creation.instance;
 
 /**
@@ -8,6 +12,6 @@
     /**
      * Creates instance of given class
      */
-    <T> T newInstance(Class<T> cls) throws InstantationException;
+    <T> T newInstance(Class<T> cls) throws InstantiationException;
 
 }
diff --git a/src/main/java/org/mockito/internal/creation/instance/InstantiatorProvider.java b/src/main/java/org/mockito/internal/creation/instance/InstantiatorProvider.java
deleted file mode 100644
index 58dc6c1..0000000
--- a/src/main/java/org/mockito/internal/creation/instance/InstantiatorProvider.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.mockito.internal.creation.instance;
-
-import org.mockito.mock.MockCreationSettings;
-
-public class InstantiatorProvider {
-
-    private final static Instantiator INSTANCE = new ObjenesisInstantiator();
-
-    public Instantiator getInstantiator(MockCreationSettings settings) {
-        if (settings.isUsingConstructor()) {
-            return new ConstructorInstantiator(settings.getOuterClassInstance());
-        } else {
-            return INSTANCE;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/instance/ObjenesisInstantiator.java b/src/main/java/org/mockito/internal/creation/instance/ObjenesisInstantiator.java
index 15172bd..a0f0980 100644
--- a/src/main/java/org/mockito/internal/creation/instance/ObjenesisInstantiator.java
+++ b/src/main/java/org/mockito/internal/creation/instance/ObjenesisInstantiator.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.creation.instance;
 
 import org.mockito.internal.configuration.GlobalConfiguration;
@@ -11,6 +15,6 @@
     private final ObjenesisStd objenesis = new ObjenesisStd(new GlobalConfiguration().enableClassCache());
 
     public <T> T newInstance(Class<T> cls) {
-        return (T) objenesis.newInstance(cls);
+        return objenesis.newInstance(cls);
     }
 }
diff --git a/src/main/java/org/mockito/internal/creation/package-info.java b/src/main/java/org/mockito/internal/creation/package-info.java
new file mode 100644
index 0000000..f4a25d7
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mock object creation.
+ */
+package org.mockito.internal.creation;
diff --git a/src/main/java/org/mockito/internal/creation/package.html b/src/main/java/org/mockito/internal/creation/package.html
deleted file mode 100644
index 533a36a..0000000
--- a/src/main/java/org/mockito/internal/creation/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Mock object creation.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java b/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java
index 52e6d19..f40450c 100644
--- a/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java
+++ b/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java
@@ -5,6 +5,7 @@
 package org.mockito.internal.creation.settings;
 
 import org.mockito.listeners.InvocationListener;
+import org.mockito.internal.listeners.StubbingLookupListener;
 import org.mockito.mock.MockCreationSettings;
 import org.mockito.mock.MockName;
 import org.mockito.mock.SerializableMode;
@@ -16,20 +17,18 @@
 import java.util.List;
 import java.util.Set;
 
-/**
- * by Szczepan Faber, created at: 4/9/12
- */
 public class CreationSettings<T> implements MockCreationSettings<T>, Serializable {
     private static final long serialVersionUID = -6789800638070123629L;
 
     protected Class<T> typeToMock;
-    protected Set<Class> extraInterfaces = new LinkedHashSet<Class>();
+    protected Set<Class<?>> extraInterfaces = new LinkedHashSet<Class<?>>();
     protected String name;
     protected Object spiedInstance;
     protected Answer<Object> defaultAnswer;
     protected MockName mockName;
     protected SerializableMode serializableMode = SerializableMode.NONE;
     protected List<InvocationListener> invocationListeners = new ArrayList<InvocationListener>();
+    protected final List<StubbingLookupListener> stubbingLookupListeners = new ArrayList<StubbingLookupListener>();
     protected boolean stubOnly;
     private boolean useConstructor;
     private Object outerClassInstance;
@@ -60,11 +59,11 @@
         return this;
     }
 
-    public Set<Class> getExtraInterfaces() {
+    public Set<Class<?>> getExtraInterfaces() {
         return extraInterfaces;
     }
 
-    public CreationSettings<T> setExtraInterfaces(Set<Class> extraInterfaces) {
+    public CreationSettings<T> setExtraInterfaces(Set<Class<?>> extraInterfaces) {
         this.extraInterfaces = extraInterfaces;
         return this;
     }
@@ -94,6 +93,11 @@
         return serializableMode != SerializableMode.NONE;
     }
 
+    public CreationSettings<T> setSerializableMode(SerializableMode serializableMode) {
+        this.serializableMode = serializableMode;
+        return this;
+    }
+
     public SerializableMode getSerializableMode() {
         return serializableMode;
     }
@@ -102,6 +106,10 @@
         return invocationListeners;
     }
 
+    public List<StubbingLookupListener> getStubbingLookupListeners() {
+        return stubbingLookupListeners;
+    }
+
     public boolean isUsingConstructor() {
         return useConstructor;
     }
diff --git a/src/main/java/org/mockito/internal/creation/util/MockitoMethodProxy.java b/src/main/java/org/mockito/internal/creation/util/MockitoMethodProxy.java
index 77ec6d1..585a0c1 100644
--- a/src/main/java/org/mockito/internal/creation/util/MockitoMethodProxy.java
+++ b/src/main/java/org/mockito/internal/creation/util/MockitoMethodProxy.java
@@ -6,5 +6,5 @@
 
 //TODO SF Replace with RealMethod and get rid of (possibly).
 public interface MockitoMethodProxy {
-    Object invokeSuper(Object target, Object[] arguments) throws Throwable;
-}
\ No newline at end of file
+    Object invokeSuper(Object target, Object[] arguments);
+}
diff --git a/src/main/java/org/mockito/internal/creation/util/SearchingClassLoader.java b/src/main/java/org/mockito/internal/creation/util/SearchingClassLoader.java
deleted file mode 100644
index 62bd0e4..0000000
--- a/src/main/java/org/mockito/internal/creation/util/SearchingClassLoader.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.creation.util;
-
-import static java.lang.Thread.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Inspired on jMock (thanks jMock guys!!!)
- */
-public class SearchingClassLoader extends ClassLoader {
-    private final ClassLoader nextToSearch;
-    
-    public SearchingClassLoader(ClassLoader parent, ClassLoader nextToSearch) {
-        super(parent);
-        this.nextToSearch = nextToSearch;
-    }
-    
-    public static ClassLoader combineLoadersOf(Class<?>... classes) {
-        return combineLoadersOf(classes[0], classes);
-    }
-    
-    private static ClassLoader combineLoadersOf(Class<?> first, Class<?>... others) {
-        List<ClassLoader> loaders = new ArrayList<ClassLoader>();
-        
-        addIfNewElement(loaders, first.getClassLoader());
-        for (Class<?> c : others) {
-            addIfNewElement(loaders, c.getClassLoader());
-        }
-        
-        // To support Eclipse Plug-in tests.
-        // In an Eclipse plug-in, we will not be on the system class loader
-        // but in the class loader of the plug-in.
-        //
-        // Note: I've been unable to reproduce the error in the test suite.
-        addIfNewElement(loaders, SearchingClassLoader.class.getClassLoader());
-        
-        // To support the Maven Surefire plugin.
-        // Note: I've been unable to reproduce the error in the test suite.
-        addIfNewElement(loaders, currentThread().getContextClassLoader());
-
-        //Had to comment that out because it didn't work with in-container Spring tests
-        //addIfNewElement(loaders, ClassLoader.getSystemClassLoader());
-        
-        return combine(loaders);
-    }
-    
-    private static ClassLoader combine(List<ClassLoader> parentLoaders) {
-        ClassLoader loader = parentLoaders.get(parentLoaders.size()-1);
-        
-        for (int i = parentLoaders.size()-2; i >= 0; i--) {
-            loader = new SearchingClassLoader(parentLoaders.get(i), loader);
-        }
-        
-        return loader;
-    }
-    
-    private static void addIfNewElement(List<ClassLoader> loaders, ClassLoader c) {
-        if (c != null && !loaders.contains(c)) {
-            loaders.add(c);
-        }
-    }
-    
-    @Override
-    protected Class<?> findClass(String name) throws ClassNotFoundException {
-        if (nextToSearch != null) {
-            return nextToSearch.loadClass(name);
-        } else {
-            return super.findClass(name); // will throw ClassNotFoundException
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/creation/util/package-info.java b/src/main/java/org/mockito/internal/creation/util/package-info.java
new file mode 100644
index 0000000..e99e60b
--- /dev/null
+++ b/src/main/java/org/mockito/internal/creation/util/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Stuff that does not have a good package yet.
+ */
+package org.mockito.internal.creation.util;
diff --git a/src/main/java/org/mockito/internal/creation/util/package.html b/src/main/java/org/mockito/internal/creation/util/package.html
deleted file mode 100644
index fb6ba2d..0000000
--- a/src/main/java/org/mockito/internal/creation/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-<body>Stuff that does not have a good package yet</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/debugging/FindingsListener.java b/src/main/java/org/mockito/internal/debugging/FindingsListener.java
index e579cbf..1aa623b 100644
--- a/src/main/java/org/mockito/internal/debugging/FindingsListener.java
+++ b/src/main/java/org/mockito/internal/debugging/FindingsListener.java
@@ -2,15 +2,15 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.debugging;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.Invocation;

-

-public interface FindingsListener {

-    void foundStubCalledWithDifferentArgs(Invocation unused, InvocationMatcher unstubbed);

-

-    void foundUnusedStub(Invocation unused);

-

-    void foundUnstubbed(InvocationMatcher unstubbed);

-}

+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+public interface FindingsListener {
+    void foundStubCalledWithDifferentArgs(Invocation unused, InvocationMatcher unstubbed);
+
+    void foundUnusedStub(Invocation unused);
+
+    void foundUnstubbed(InvocationMatcher unstubbed);
+}
diff --git a/src/main/java/org/mockito/internal/debugging/InvocationsPrinter.java b/src/main/java/org/mockito/internal/debugging/InvocationsPrinter.java
new file mode 100644
index 0000000..2f0c06b
--- /dev/null
+++ b/src/main/java/org/mockito/internal/debugging/InvocationsPrinter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.Mockito;
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.invocation.Invocation;
+import org.mockito.stubbing.Stubbing;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * Prints invocations in human-readable, printable way
+ */
+public class InvocationsPrinter {
+
+    public String printInvocations(Object mock) {
+        Collection<Invocation> invocations = Mockito.mockingDetails(mock).getInvocations();
+        Collection<Stubbing> stubbings = Mockito.mockingDetails(mock).getStubbings();
+        if (invocations.isEmpty() && stubbings.isEmpty()) {
+            return "No interactions and stubbings found for mock: " + mock;
+        }
+
+        StringBuilder sb = new StringBuilder();
+        int x = 1;
+        for(Invocation i:invocations) {
+            if (x == 1) {
+                sb.append("[Mockito] Interactions of: ").append(mock).append("\n");
+            }
+            sb.append(" ").append(x++).append(". ").append(i.toString()).append("\n");
+            sb.append("  ").append(i.getLocation()).append("\n");
+            if (i.stubInfo() != null) {
+                sb.append("   - stubbed ").append(i.stubInfo().stubbedAt()).append("\n");
+            }
+        }
+
+        LinkedList<Stubbing> unused = ListUtil.filter(stubbings, new ListUtil.Filter<Stubbing>() {
+            public boolean isOut(Stubbing s) {
+                return s.wasUsed();
+            }
+        });
+
+        if (unused.isEmpty()) {
+            return sb.toString();
+        }
+        sb.append("[Mockito] Unused stubbings of: " + mock).append("\n");
+
+        x = 1;
+        for(Stubbing s:stubbings) {
+            sb.append(" ").append(x++).append(". ").append(s.getInvocation()).append("\n");
+            sb.append("  - stubbed ").append(s.getInvocation().getLocation()).append("\n");
+        }
+        return sb.toString();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/Localized.java b/src/main/java/org/mockito/internal/debugging/Localized.java
index 619e466..0588042 100644
--- a/src/main/java/org/mockito/internal/debugging/Localized.java
+++ b/src/main/java/org/mockito/internal/debugging/Localized.java
@@ -2,26 +2,26 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.debugging;

-

-

-import org.mockito.invocation.Location;

-

-public class Localized<T> {

-

-    private final T object;

-    private final Location location;

-

-    public Localized(T object) {

-        this.object = object;

-        location = new LocationImpl();

-    }

-

-    public T getObject() {

-        return object;

-    }

-

-    public Location getLocation() {

-        return location;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.debugging;
+
+
+import org.mockito.invocation.Location;
+
+public class Localized<T> {
+
+    private final T object;
+    private final Location location;
+
+    public Localized(T object) {
+        this.object = object;
+        location = new LocationImpl();
+    }
+
+    public T getObject() {
+        return object;
+    }
+
+    public Location getLocation() {
+        return location;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/LocationImpl.java b/src/main/java/org/mockito/internal/debugging/LocationImpl.java
index d04c513..c661ced 100644
--- a/src/main/java/org/mockito/internal/debugging/LocationImpl.java
+++ b/src/main/java/org/mockito/internal/debugging/LocationImpl.java
@@ -1,35 +1,35 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.debugging;

-

-import org.mockito.internal.exceptions.stacktrace.StackTraceFilter;

-import org.mockito.invocation.Location;

-

-import java.io.Serializable;

-

-public class LocationImpl implements Location, Serializable {

-

-    private static final long serialVersionUID = -9054861157390980624L;

-    private final Throwable stackTraceHolder;

-    private final StackTraceFilter stackTraceFilter;

-

-    public LocationImpl() {

-        this(new StackTraceFilter());

-    }

-

-    public LocationImpl(StackTraceFilter stackTraceFilter) {

-        this.stackTraceFilter = stackTraceFilter;

-        stackTraceHolder = new Throwable();

-    }

-	

-    @Override

-    public String toString() {

-        StackTraceElement[] filtered = stackTraceFilter.filter(stackTraceHolder.getStackTrace(), false);

-        if (filtered.length == 0) {

-            return "-> at <<unknown line>>";

-        }

-        return "-> at " + filtered[0].toString();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import java.io.Serializable;
+import org.mockito.internal.exceptions.stacktrace.StackTraceFilter;
+import org.mockito.invocation.Location;
+
+public class LocationImpl implements Location, Serializable {
+
+    private static final long serialVersionUID = -9054861157390980624L;
+    private final Throwable stackTraceHolder;
+    private final StackTraceFilter stackTraceFilter;
+
+    public LocationImpl() {
+        this(new StackTraceFilter());
+    }
+
+    public LocationImpl(StackTraceFilter stackTraceFilter) {
+        this.stackTraceFilter = stackTraceFilter;
+        stackTraceHolder = new Throwable();
+    }
+
+    @Override
+    public String toString() {
+        //TODO SF perhaps store the results after invocation?
+        StackTraceElement[] filtered = stackTraceFilter.filter(stackTraceHolder.getStackTrace(), false);
+        if (filtered.length == 0) {
+            return "-> at <<unknown line>>";
+        }
+        return "-> at " + filtered[0].toString();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/LoggingListener.java b/src/main/java/org/mockito/internal/debugging/LoggingListener.java
index e31a5bb..d014e87 100644
--- a/src/main/java/org/mockito/internal/debugging/LoggingListener.java
+++ b/src/main/java/org/mockito/internal/debugging/LoggingListener.java
@@ -1,52 +1,89 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.debugging;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.internal.util.MockitoLogger;

-import org.mockito.invocation.Invocation;

-

-import static org.mockito.internal.util.StringJoiner.join;

-

-public class LoggingListener implements FindingsListener {

-    private final boolean warnAboutUnstubbed;

-    private final MockitoLogger logger;

-

-    public LoggingListener(boolean warnAboutUnstubbed, MockitoLogger logger) {

-        this.warnAboutUnstubbed = warnAboutUnstubbed;

-        this.logger = logger;

-    }

-

-    public void foundStubCalledWithDifferentArgs(Invocation unused, InvocationMatcher unstubbed) {

-        logger.log(join(

-                " *** Stubbing warnings from Mockito: *** ",

-                "",

-                "stubbed with those args here   " + unused.getLocation(),

-                "BUT called with different args " + unstubbed.getInvocation().getLocation(),

-                ""));

-    }

-

-    public void foundUnusedStub(Invocation unused) {

-        logger.log("This stubbing was never used   " + unused.getLocation() + "\n");

-    }

-

-    public void foundUnstubbed(InvocationMatcher unstubbed) {

-        if (warnAboutUnstubbed) {

-            logger.log(join(

-                    "This method was not stubbed ",

-                    unstubbed,

-                    unstubbed.getInvocation().getLocation(),

-                    ""));

-        }

-    }

-

-    public boolean isWarnAboutUnstubbed() {

-        return warnAboutUnstubbed;

-    }

-

-    public MockitoLogger getLogger() {

-        return logger;

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.mockito.internal.util.StringUtil.join;
+
+public class LoggingListener implements FindingsListener {
+    private final boolean warnAboutUnstubbed;
+
+    private final List<String> argMismatchStubs = new LinkedList<String>();
+    private final List<String> unusedStubs = new LinkedList<String>();
+    private final List<String> unstubbedCalls = new LinkedList<String>();
+
+    public LoggingListener(boolean warnAboutUnstubbed) {
+        this.warnAboutUnstubbed = warnAboutUnstubbed;
+    }
+
+    public void foundStubCalledWithDifferentArgs(Invocation unused, InvocationMatcher unstubbed) {
+        //TODO there is not good reason we should get Invocation and InvocationMatcher here
+        // we should pass 2 InvocationMatchers and testing is easier
+        // it's also confusing that unstubbed invocation is passed as InvocationMatcher (should be rather Invocation)
+
+        //this information comes in pairs
+        String index = Integer.toString(indexOfNextPair(argMismatchStubs.size()));
+        //making sure indentation is correct
+        String padding = index.replaceAll("\\d", " ");
+        argMismatchStubs.add(index +   ". Stubbed " + unused.getLocation());
+        argMismatchStubs.add(padding + "  Invoked " + unstubbed.getInvocation().getLocation());
+    }
+
+    static int indexOfNextPair(int collectionSize) {
+        return (collectionSize / 2) + 1;
+    }
+
+    public void foundUnusedStub(Invocation unused) {
+        unusedStubs.add((unusedStubs.size() + 1) + ". " + unused.getLocation());
+    }
+
+    public void foundUnstubbed(InvocationMatcher unstubbed) {
+        if (warnAboutUnstubbed) {
+            unstubbedCalls.add((unstubbedCalls.size() + 1) + ". " + unstubbed.getInvocation().getLocation());
+        }
+    }
+
+    public String getStubbingInfo() {
+        if (argMismatchStubs.isEmpty() && unusedStubs.isEmpty() && unstubbedCalls.isEmpty()) {
+            return "";
+        }
+
+        List<String> lines = new LinkedList<String>();
+        lines.add("[Mockito] Additional stubbing information (see javadoc for StubbingInfo class):");
+
+        if (!argMismatchStubs.isEmpty()) {
+            lines.add("[Mockito]");
+            lines.add("[Mockito] Argument mismatch between stubbing and actual invocation (is stubbing correct in the test?):");
+            lines.add("[Mockito]");
+            addOrderedList(lines, argMismatchStubs);
+        }
+
+        if (!unusedStubs.isEmpty()) {
+            lines.add("[Mockito]");
+            lines.add("[Mockito] Unused stubbing (perhaps can be removed from the test?):");
+            lines.add("[Mockito]");
+            addOrderedList(lines, unusedStubs);
+        }
+
+        if (!unstubbedCalls.isEmpty()) {
+            lines.add("[Mockito]");
+            lines.add("[Mockito] Unstubbed method invocations (perhaps missing stubbing in the test?):");
+            lines.add("[Mockito]");
+            addOrderedList(lines, unstubbedCalls);
+        }
+        return join("", lines);
+    }
+
+    private void addOrderedList(List<String> target, List<String> additions) {
+        for (String a : additions) {
+            target.add("[Mockito] " + a);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/MockitoDebuggerImpl.java b/src/main/java/org/mockito/internal/debugging/MockitoDebuggerImpl.java
index 2e82abb..c14f0ab 100644
--- a/src/main/java/org/mockito/internal/debugging/MockitoDebuggerImpl.java
+++ b/src/main/java/org/mockito/internal/debugging/MockitoDebuggerImpl.java
@@ -1,58 +1,61 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.debugging;

-

-import org.mockito.MockitoDebugger;

-import org.mockito.internal.invocation.UnusedStubsFinder;

-import org.mockito.internal.invocation.finder.AllInvocationsFinder;

-import org.mockito.invocation.Invocation;

-

-import java.util.List;

-

-import static java.util.Arrays.asList;

-

-public class MockitoDebuggerImpl implements MockitoDebugger {

-

-    private final AllInvocationsFinder allInvocationsFinder = new AllInvocationsFinder();

-    private final UnusedStubsFinder unusedStubsFinder = new UnusedStubsFinder();

-

-    public String printInvocations(Object ... mocks) {

-        String out = "";

-        List<Invocation> invocations = allInvocationsFinder.find(asList(mocks));

-        out += line("********************************");

-        out += line("*** Mockito interactions log ***");

-        out += line("********************************");

-        for(Invocation i:invocations) {

-            out += line(i.toString());

-            out += line(" invoked: " + i.getLocation());

-            if (i.stubInfo() != null) {

-                out += line(" stubbed: " + i.stubInfo().stubbedAt().toString());

-            }

-        }

-

-        invocations = unusedStubsFinder.find(asList(mocks));

-        if (invocations.isEmpty()) {

-            return print(out);

-        }

-        out += line("********************************");

-        out += line("***       Unused stubs       ***");

-        out += line("********************************");

-        

-        for(Invocation i:invocations) {

-            out += line(i.toString());

-            out += line(" stubbed: " + i.getLocation());

-        }

-        return print(out);

-    }

-

-    private String line(String text) {

-        return text + "\n";

-    }

-

-    private String print(String out) {

-        System.out.println(out);

-        return out;

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.MockitoDebugger;
+import org.mockito.internal.invocation.UnusedStubsFinder;
+import org.mockito.internal.invocation.finder.AllInvocationsFinder;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+public class MockitoDebuggerImpl implements MockitoDebugger {
+
+    private final UnusedStubsFinder unusedStubsFinder = new UnusedStubsFinder();
+
+    /**
+     * TODO: when MockitoDebugger is deleted, delete this implementation, too
+     */
+    @Deprecated
+    public String printInvocations(Object ... mocks) {
+        String out = "";
+        List<Invocation> invocations = AllInvocationsFinder.find(asList(mocks));
+        out += line("********************************");
+        out += line("*** Mockito interactions log ***");
+        out += line("********************************");
+        for(Invocation i:invocations) {
+            out += line(i.toString());
+            out += line(" invoked: " + i.getLocation());
+            if (i.stubInfo() != null) {
+                out += line(" stubbed: " + i.stubInfo().stubbedAt().toString());
+            }
+        }
+
+        invocations = unusedStubsFinder.find(asList(mocks));
+        if (invocations.isEmpty()) {
+            return print(out);
+        }
+        out += line("********************************");
+        out += line("***       Unused stubs       ***");
+        out += line("********************************");
+
+        for(Invocation i:invocations) {
+            out += line(i.toString());
+            out += line(" stubbed: " + i.getLocation());
+        }
+        return print(out);
+    }
+
+    private String line(String text) {
+        return text + "\n";
+    }
+
+    private String print(String out) {
+        System.out.println(out);
+        return out;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/VerboseMockInvocationLogger.java b/src/main/java/org/mockito/internal/debugging/VerboseMockInvocationLogger.java
index 2a81074..c7b6ff6 100644
--- a/src/main/java/org/mockito/internal/debugging/VerboseMockInvocationLogger.java
+++ b/src/main/java/org/mockito/internal/debugging/VerboseMockInvocationLogger.java
@@ -5,23 +5,22 @@
 
 package org.mockito.internal.debugging;
 
+import java.io.PrintStream;
 import org.mockito.invocation.DescribedInvocation;
 import org.mockito.listeners.InvocationListener;
 import org.mockito.listeners.MethodInvocationReport;
 
-import java.io.PrintStream;
-
 /**
  * Logs all invocations to standard output.
- * 
- * Used for debugging interactions with a mock. 
+ *
+ * Used for debugging interactions with a mock.
  */
 public class VerboseMockInvocationLogger implements InvocationListener {
 
     // visible for testing
-	final PrintStream printStream;
+    final PrintStream printStream;
 
-	private int mockInvocationsCounter = 0;
+    private int mockInvocationsCounter = 0;
 
     public VerboseMockInvocationLogger() {
         this(System.out);
@@ -56,22 +55,22 @@
     }
 
     private void printHeader() {
-		mockInvocationsCounter++;
-		printStream.println("############ Logging method invocation #" + mockInvocationsCounter + " on mock/spy ########");
-	}
+        mockInvocationsCounter++;
+        printStream.println("############ Logging method invocation #" + mockInvocationsCounter + " on mock/spy ########");
+    }
 
     private void printInvocation(DescribedInvocation invocation) {
-		printStream.println(invocation.toString());
-//		printStream.println("Handling method call on a mock/spy.");
-		printlnIndented("invoked: " + invocation.getLocation().toString());
-	}
+        printStream.println(invocation.toString());
+//        printStream.println("Handling method call on a mock/spy.");
+        printlnIndented("invoked: " + invocation.getLocation().toString());
+    }
 
-	private void printFooter() {
-		printStream.println("");
-	}
-	
-	private void printlnIndented(String message) {
-		printStream.println("   " + message);
-	}
-	
+    private void printFooter() {
+        printStream.println("");
+    }
+
+    private void printlnIndented(String message) {
+        printStream.println("   " + message);
+    }
+
 }
diff --git a/src/main/java/org/mockito/internal/debugging/WarningsCollector.java b/src/main/java/org/mockito/internal/debugging/WarningsCollector.java
index 6a870d4..3fb3e0e 100644
--- a/src/main/java/org/mockito/internal/debugging/WarningsCollector.java
+++ b/src/main/java/org/mockito/internal/debugging/WarningsCollector.java
@@ -2,37 +2,30 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.debugging;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.internal.invocation.UnusedStubsFinder;

-import org.mockito.internal.invocation.finder.AllInvocationsFinder;

-import org.mockito.internal.listeners.CollectCreatedMocks;

-import org.mockito.internal.progress.MockingProgress;

-import org.mockito.internal.progress.ThreadSafeMockingProgress;

-import org.mockito.invocation.Invocation;

-

-import java.util.LinkedList;

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public class WarningsCollector {

-   

-    List createdMocks;

-

-    public WarningsCollector() {

-        createdMocks = new LinkedList();

-        MockingProgress progress = new ThreadSafeMockingProgress();

-        progress.setListener(new CollectCreatedMocks(createdMocks));

-    }

-

-    public String getWarnings() {

-        List<Invocation> unused = new UnusedStubsFinder().find(createdMocks);

-        List<Invocation> all = new AllInvocationsFinder().find(createdMocks);

-        List<InvocationMatcher> allInvocationMatchers = InvocationMatcher.createFrom(all);

-

-        String warnings = new WarningsPrinterImpl(unused, allInvocationMatchers, false).print();

-

-        return warnings;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.UnusedStubsFinder;
+import org.mockito.internal.invocation.finder.AllInvocationsFinder;
+import org.mockito.invocation.Invocation;
+
+import java.util.LinkedList;
+import java.util.List;
+
+@Deprecated
+public class WarningsCollector {
+
+    private final List<Object> createdMocks;
+
+    public WarningsCollector() {
+        createdMocks = new LinkedList<Object>();
+    }
+
+    public String getWarnings() {
+        List<Invocation> unused = new UnusedStubsFinder().find(createdMocks);
+        List<Invocation> all = AllInvocationsFinder.find(createdMocks);
+        List<InvocationMatcher> allInvocationMatchers = InvocationMatcher.createFrom(all);
+
+        return new WarningsPrinterImpl(unused, allInvocationMatchers, false).print();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/WarningsFinder.java b/src/main/java/org/mockito/internal/debugging/WarningsFinder.java
index 08ffb3e..8b7c457 100644
--- a/src/main/java/org/mockito/internal/debugging/WarningsFinder.java
+++ b/src/main/java/org/mockito/internal/debugging/WarningsFinder.java
@@ -2,49 +2,48 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.debugging;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.Invocation;

-

-import java.util.Iterator;

-import java.util.LinkedList;

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public class WarningsFinder {

-    private final List<Invocation> baseUnusedStubs;

-    private final List<InvocationMatcher> baseAllInvocations;

-

-    public WarningsFinder(List<Invocation> unusedStubs, List<InvocationMatcher> allInvocations) {

-        this.baseUnusedStubs = unusedStubs;

-        this.baseAllInvocations = allInvocations;

-    }

-    

-    public void find(FindingsListener findingsListener) {

-        List<Invocation> unusedStubs = new LinkedList(this.baseUnusedStubs);

-        List<InvocationMatcher> allInvocations = new LinkedList(this.baseAllInvocations);

-

-        Iterator<Invocation> unusedIterator = unusedStubs.iterator();

-        while(unusedIterator.hasNext()) {

-            Invocation unused = unusedIterator.next();

-            Iterator<InvocationMatcher> unstubbedIterator = allInvocations.iterator();

-            while(unstubbedIterator.hasNext()) {

-                InvocationMatcher unstubbed = unstubbedIterator.next();

-                if(unstubbed.hasSimilarMethod(unused)) {

-                    findingsListener.foundStubCalledWithDifferentArgs(unused, unstubbed);

-                    unusedIterator.remove();

-                    unstubbedIterator.remove();

-                }

-            }

-        }

-

-        for (Invocation i : unusedStubs) {

-            findingsListener.foundUnusedStub(i);

-        }

-

-        for (InvocationMatcher i : allInvocations) {

-            findingsListener.foundUnstubbed(i);

-        }

-    }

-}

+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class WarningsFinder {
+    private final List<Invocation> baseUnusedStubs;
+    private final List<InvocationMatcher> baseAllInvocations;
+
+    public WarningsFinder(List<Invocation> unusedStubs, List<InvocationMatcher> allInvocations) {
+        this.baseUnusedStubs = unusedStubs;
+        this.baseAllInvocations = allInvocations;
+    }
+
+    public void find(FindingsListener findingsListener) {
+        List<Invocation> unusedStubs = new LinkedList<Invocation>(this.baseUnusedStubs);
+        List<InvocationMatcher> allInvocations = new LinkedList<InvocationMatcher>(this.baseAllInvocations);
+
+        Iterator<Invocation> unusedIterator = unusedStubs.iterator();
+        while(unusedIterator.hasNext()) {
+            Invocation unused = unusedIterator.next();
+            Iterator<InvocationMatcher> unstubbedIterator = allInvocations.iterator();
+            while(unstubbedIterator.hasNext()) {
+                InvocationMatcher unstubbed = unstubbedIterator.next();
+                if(unstubbed.hasSimilarMethod(unused)) {
+                    findingsListener.foundStubCalledWithDifferentArgs(unused, unstubbed);
+                    unusedIterator.remove();
+                    unstubbedIterator.remove();
+                }
+            }
+        }
+
+        for (Invocation i : unusedStubs) {
+            findingsListener.foundUnusedStub(i);
+        }
+
+        for (InvocationMatcher i : allInvocations) {
+            findingsListener.foundUnstubbed(i);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/WarningsPrinterImpl.java b/src/main/java/org/mockito/internal/debugging/WarningsPrinterImpl.java
index 2e6a75a..ca18e85 100644
--- a/src/main/java/org/mockito/internal/debugging/WarningsPrinterImpl.java
+++ b/src/main/java/org/mockito/internal/debugging/WarningsPrinterImpl.java
@@ -1,41 +1,31 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.debugging;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.internal.util.MockitoLogger;

-import org.mockito.internal.util.SimpleMockitoLogger;

-import org.mockito.invocation.Invocation;

-

-import java.util.List;

-

-public class WarningsPrinterImpl {

-

-    private final boolean warnAboutUnstubbed;

-    private final WarningsFinder finder;

-

-    public WarningsPrinterImpl(List<Invocation> unusedStubs, List<InvocationMatcher> unstubbedInvocations) {

-        this(unusedStubs, unstubbedInvocations, false);

-    }

-

-    public WarningsPrinterImpl(List<Invocation> unusedStubs, List<InvocationMatcher> allInvocations, boolean warnAboutUnstubbed) {

-        this(warnAboutUnstubbed, new WarningsFinder(unusedStubs, allInvocations));

-    }

-

-    WarningsPrinterImpl(boolean warnAboutUnstubbed, WarningsFinder finder) {

-        this.warnAboutUnstubbed = warnAboutUnstubbed;

-        this.finder = finder;

-    }

-    

-    public void print(final MockitoLogger logger) {

-        finder.find(new LoggingListener(warnAboutUnstubbed, logger));

-    }

-

-    public String print() {

-        SimpleMockitoLogger logger = new SimpleMockitoLogger();

-        this.print(logger);

-        return logger.getLoggedInfo();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+public class WarningsPrinterImpl {
+
+    private final boolean warnAboutUnstubbed;
+    private final WarningsFinder finder;
+
+    public WarningsPrinterImpl(List<Invocation> unusedStubs, List<InvocationMatcher> allInvocations, boolean warnAboutUnstubbed) {
+        this(warnAboutUnstubbed, new WarningsFinder(unusedStubs, allInvocations));
+    }
+
+    WarningsPrinterImpl(boolean warnAboutUnstubbed, WarningsFinder finder) {
+        this.warnAboutUnstubbed = warnAboutUnstubbed;
+        this.finder = finder;
+    }
+
+    public String print() {
+        LoggingListener listener = new LoggingListener(warnAboutUnstubbed);
+        finder.find(listener);
+        return listener.getStubbingInfo();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/debugging/package-info.java b/src/main/java/org/mockito/internal/debugging/package-info.java
new file mode 100644
index 0000000..bd844e3
--- /dev/null
+++ b/src/main/java/org/mockito/internal/debugging/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Whatever helps in debugging failed tests.
+ */
+package org.mockito.internal.debugging;
diff --git a/src/main/java/org/mockito/internal/debugging/package.html b/src/main/java/org/mockito/internal/debugging/package.html
deleted file mode 100644
index 13cee40..0000000
--- a/src/main/java/org/mockito/internal/debugging/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Whatever helps in debugging failed tests
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java b/src/main/java/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java
index 272187a..d4f3e0e 100644
--- a/src/main/java/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java
+++ b/src/main/java/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java
@@ -2,12 +2,12 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.exceptions;

-

-public class ExceptionIncludingMockitoWarnings extends RuntimeException {

-    private static final long serialVersionUID = -5925150219446765679L;

-

-    public ExceptionIncludingMockitoWarnings(String message, Throwable throwable) {

-        super(message, throwable);

-    }

-}

+package org.mockito.internal.exceptions;
+
+public class ExceptionIncludingMockitoWarnings extends RuntimeException {
+    private static final long serialVersionUID = -5925150219446765679L;
+
+    public ExceptionIncludingMockitoWarnings(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/exceptions/MockitoLimitations.java b/src/main/java/org/mockito/internal/exceptions/MockitoLimitations.java
index bc6d9ba..c8edc79 100644
--- a/src/main/java/org/mockito/internal/exceptions/MockitoLimitations.java
+++ b/src/main/java/org/mockito/internal/exceptions/MockitoLimitations.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.exceptions;
 
 public class MockitoLimitations {
diff --git a/src/main/java/org/mockito/internal/exceptions/Reporter.java b/src/main/java/org/mockito/internal/exceptions/Reporter.java
new file mode 100644
index 0000000..bb4ae6c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/exceptions/Reporter.java
@@ -0,0 +1,902 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.exceptions;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.*;
+import org.mockito.exceptions.verification.*;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.exceptions.util.ScenarioPrinter;
+import org.mockito.internal.junit.ExceptionFactory;
+import org.mockito.internal.matchers.LocalizedMatcher;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.invocation.Location;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockName;
+import org.mockito.mock.SerializableMode;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.mockito.internal.reporting.Pluralizer.pluralize;
+import static org.mockito.internal.reporting.Pluralizer.were_exactly_x_interactions;
+import static org.mockito.internal.util.StringUtil.join;
+
+/**
+ * Reports verification and misusing errors.
+ * <p>
+ * One of the key points of mocking library is proper verification/exception
+ * messages. All messages in one place makes it easier to tune and amend them.
+ * <p>
+ * Reporter can be injected and therefore is easily testable.
+ * <p>
+ * Generally, exception messages are full of line breaks to make them easy to
+ * read (xunit plugins take only fraction of screen on modern IDEs).
+ */
+public class Reporter {
+
+    private Reporter() {
+    }
+
+    public static MockitoException checkedExceptionInvalid(Throwable t) {
+        return new MockitoException(join(
+                "Checked exception is invalid for this method!",
+                "Invalid: " + t
+        ));
+    }
+
+    public static MockitoException cannotStubWithNullThrowable() {
+        return new MockitoException(join(
+                "Cannot stub with null throwable!"
+        ));
+
+    }
+
+    public static MockitoException unfinishedStubbing(Location location) {
+        return new UnfinishedStubbingException(join(
+                "Unfinished stubbing detected here:",
+                location,
+                "",
+                "E.g. thenReturn() may be missing.",
+                "Examples of correct stubbing:",
+                "    when(mock.isOk()).thenReturn(true);",
+                "    when(mock.isOk()).thenThrow(exception);",
+                "    doThrow(exception).when(mock).someVoidMethod();",
+                "Hints:",
+                " 1. missing thenReturn()",
+                " 2. you are trying to stub a final method, which is not supported",
+                " 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed",
+                ""
+        ));
+    }
+
+    public static MockitoException incorrectUseOfApi() {
+        return new MockitoException(join(
+                "Incorrect use of API detected here:",
+                new LocationImpl(),
+                "",
+                "You probably stored a reference to OngoingStubbing returned by when() and called stubbing methods like thenReturn() on this reference more than once.",
+                "Examples of correct usage:",
+                "    when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);",
+                "    when(mock.isOk()).thenReturn(true, false).thenThrow(exception);",
+                ""
+        ));
+    }
+
+    public static MockitoException missingMethodInvocation() {
+        return new MissingMethodInvocationException(join(
+                "when() requires an argument which has to be 'a method call on a mock'.",
+                "For example:",
+                "    when(mock.getArticles()).thenReturn(articles);",
+                "",
+                "Also, this error might show up because:",
+                "1. you stub either of: final/private/equals()/hashCode() methods.",
+                "   Those methods *cannot* be stubbed/verified.",
+                "   " + MockitoLimitations.NON_PUBLIC_PARENT,
+                "2. inside when() you don't call method on mock but on some other object.",
+                ""
+        ));
+    }
+
+    public static MockitoException unfinishedVerificationException(Location location) {
+        return new UnfinishedVerificationException(join(
+                "Missing method call for verify(mock) here:",
+                location,
+                "",
+                "Example of correct verification:",
+                "    verify(mock).doSomething()",
+                "",
+                "Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.",
+                "Those methods *cannot* be stubbed/verified.",
+                MockitoLimitations.NON_PUBLIC_PARENT,
+                ""
+        ));
+    }
+
+    public static MockitoException notAMockPassedToVerify(Class<?> type) {
+        return new NotAMockException(join(
+                "Argument passed to verify() is of type " + type.getSimpleName() + " and is not a mock!",
+                "Make sure you place the parenthesis correctly!",
+                "See the examples of correct verifications:",
+                "    verify(mock).someMethod();",
+                "    verify(mock, times(10)).someMethod();",
+                "    verify(mock, atLeastOnce()).someMethod();"
+        ));
+    }
+
+    public static MockitoException nullPassedToVerify() {
+        return new NullInsteadOfMockException(join(
+                "Argument passed to verify() should be a mock but is null!",
+                "Examples of correct verifications:",
+                "    verify(mock).someMethod();",
+                "    verify(mock, times(10)).someMethod();",
+                "    verify(mock, atLeastOnce()).someMethod();",
+                "    not: verify(mock.someMethod());",
+                "Also, if you use @Mock annotation don't miss initMocks()"
+        ));
+    }
+
+    public static MockitoException notAMockPassedToWhenMethod() {
+        return new NotAMockException(join(
+                "Argument passed to when() is not a mock!",
+                "Example of correct stubbing:",
+                "    doThrow(new RuntimeException()).when(mock).someMethod();"
+        ));
+    }
+
+    public static MockitoException nullPassedToWhenMethod() {
+        return new NullInsteadOfMockException(join(
+                "Argument passed to when() is null!",
+                "Example of correct stubbing:",
+                "    doThrow(new RuntimeException()).when(mock).someMethod();",
+                "Also, if you use @Mock annotation don't miss initMocks()"
+        ));
+    }
+
+    public static MockitoException mocksHaveToBePassedToVerifyNoMoreInteractions() {
+        return new MockitoException(join(
+                "Method requires argument(s)!",
+                "Pass mocks that should be verified, e.g:",
+                "    verifyNoMoreInteractions(mockOne, mockTwo);",
+                "    verifyZeroInteractions(mockOne, mockTwo);",
+                ""
+        ));
+    }
+
+    public static MockitoException notAMockPassedToVerifyNoMoreInteractions() {
+        return new NotAMockException(join(
+                "Argument(s) passed is not a mock!",
+                "Examples of correct verifications:",
+                "    verifyNoMoreInteractions(mockOne, mockTwo);",
+                "    verifyZeroInteractions(mockOne, mockTwo);",
+                ""
+        ));
+    }
+
+    public static MockitoException nullPassedToVerifyNoMoreInteractions() {
+        return new NullInsteadOfMockException(join(
+                "Argument(s) passed is null!",
+                "Examples of correct verifications:",
+                "    verifyNoMoreInteractions(mockOne, mockTwo);",
+                "    verifyZeroInteractions(mockOne, mockTwo);"
+        ));
+    }
+
+    public static MockitoException notAMockPassedWhenCreatingInOrder() {
+        return new NotAMockException(join(
+                "Argument(s) passed is not a mock!",
+                "Pass mocks that require verification in order.",
+                "For example:",
+                "    InOrder inOrder = inOrder(mockOne, mockTwo);"
+        ));
+    }
+
+    public static MockitoException nullPassedWhenCreatingInOrder() {
+        return new NullInsteadOfMockException(join(
+                "Argument(s) passed is null!",
+                "Pass mocks that require verification in order.",
+                "For example:",
+                "    InOrder inOrder = inOrder(mockOne, mockTwo);"
+        ));
+    }
+
+    public static MockitoException mocksHaveToBePassedWhenCreatingInOrder() {
+        return new MockitoException(join(
+                "Method requires argument(s)!",
+                "Pass mocks that require verification in order.",
+                "For example:",
+                "    InOrder inOrder = inOrder(mockOne, mockTwo);"
+        ));
+    }
+
+    public static MockitoException inOrderRequiresFamiliarMock() {
+        return new MockitoException(join(
+                "InOrder can only verify mocks that were passed in during creation of InOrder.",
+                "For example:",
+                "    InOrder inOrder = inOrder(mockOne);",
+                "    inOrder.verify(mockOne).doStuff();"
+        ));
+    }
+
+    public static MockitoException invalidUseOfMatchers(int expectedMatchersCount, List<LocalizedMatcher> recordedMatchers) {
+        return new InvalidUseOfMatchersException(join(
+                "Invalid use of argument matchers!",
+                expectedMatchersCount + " matchers expected, " + recordedMatchers.size() + " recorded:" +
+                        locationsOf(recordedMatchers),
+                "",
+                "This exception may occur if matchers are combined with raw values:",
+                "    //incorrect:",
+                "    someMethod(anyObject(), \"raw String\");",
+                "When using matchers, all arguments have to be provided by matchers.",
+                "For example:",
+                "    //correct:",
+                "    someMethod(anyObject(), eq(\"String by matcher\"));",
+                "",
+                "For more info see javadoc for Matchers class.",
+                ""
+        ));
+    }
+
+    public static MockitoException incorrectUseOfAdditionalMatchers(String additionalMatcherName, int expectedSubMatchersCount, Collection<LocalizedMatcher> matcherStack) {
+        return new InvalidUseOfMatchersException(join(
+                "Invalid use of argument matchers inside additional matcher " + additionalMatcherName + " !",
+                new LocationImpl(),
+                "",
+                expectedSubMatchersCount + " sub matchers expected, " + matcherStack.size() + " recorded:",
+                locationsOf(matcherStack),
+                "",
+                "This exception may occur if matchers are combined with raw values:",
+                "    //incorrect:",
+                "    someMethod(AdditionalMatchers.and(isNotNull(), \"raw String\");",
+                "When using matchers, all arguments have to be provided by matchers.",
+                "For example:",
+                "    //correct:",
+                "    someMethod(AdditionalMatchers.and(isNotNull(), eq(\"raw String\"));",
+                "",
+                "For more info see javadoc for Matchers and AdditionalMatchers classes.",
+                ""
+        ));
+    }
+
+    public static MockitoException stubPassedToVerify() {
+        return new CannotVerifyStubOnlyMock(join(
+                "Argument passed to verify() is a stubOnly() mock, not a full blown mock!",
+                "If you intend to verify invocations on a mock, don't use stubOnly() in its MockSettings."
+        ));
+    }
+
+    public static MockitoException reportNoSubMatchersFound(String additionalMatcherName) {
+        return new InvalidUseOfMatchersException(join(
+                "No matchers found for additional matcher " + additionalMatcherName,
+                new LocationImpl(),
+                ""
+        ));
+    }
+
+
+    private static Object locationsOf(Collection<LocalizedMatcher> matchers) {
+        List<String> description = new ArrayList<String>();
+        for (LocalizedMatcher matcher : matchers)
+            description.add(matcher.getLocation().toString());
+        return join(description.toArray());
+    }
+
+    public static AssertionError argumentsAreDifferent(String wanted, String actual, Location actualLocation) {
+        String message = join("Argument(s) are different! Wanted:",
+                              wanted,
+                              new LocationImpl(),
+                              "Actual invocation has different arguments:",
+                              actual,
+                              actualLocation,
+                              ""
+        );
+
+        return ExceptionFactory.createArgumentsAreDifferentException(message, wanted, actual);
+    }
+
+    public static MockitoAssertionError wantedButNotInvoked(DescribedInvocation wanted) {
+        return new WantedButNotInvoked(createWantedButNotInvokedMessage(wanted));
+    }
+
+    public static MockitoAssertionError wantedButNotInvoked(DescribedInvocation wanted, List<? extends DescribedInvocation> invocations) {
+        String allInvocations;
+        if (invocations.isEmpty()) {
+            allInvocations = "Actually, there were zero interactions with this mock.\n";
+        } else {
+            StringBuilder sb = new StringBuilder(
+                    "\nHowever, there " + were_exactly_x_interactions(invocations.size()) + " with this mock:\n");
+            for (DescribedInvocation i : invocations) {
+                sb.append(i.toString())
+                  .append("\n")
+                  .append(i.getLocation())
+                  .append("\n\n");
+            }
+            allInvocations = sb.toString();
+        }
+
+        String message = createWantedButNotInvokedMessage(wanted);
+        return new WantedButNotInvoked(message + allInvocations);
+    }
+
+    private static String createWantedButNotInvokedMessage(DescribedInvocation wanted) {
+        return join(
+                "Wanted but not invoked:",
+                wanted.toString(),
+                new LocationImpl(),
+                ""
+        );
+    }
+
+    public static MockitoAssertionError wantedButNotInvokedInOrder(DescribedInvocation wanted, DescribedInvocation previous) {
+        return new VerificationInOrderFailure(join(
+                "Verification in order failure",
+                "Wanted but not invoked:",
+                wanted.toString(),
+                new LocationImpl(),
+                "Wanted anywhere AFTER following interaction:",
+                previous.toString(),
+                previous.getLocation(),
+                ""
+        ));
+    }
+
+    public static MockitoAssertionError tooManyActualInvocations(int wantedCount, int actualCount, DescribedInvocation wanted, Location firstUndesired) {
+        String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, firstUndesired);
+        return new TooManyActualInvocations(message);
+    }
+
+    private static String createTooManyInvocationsMessage(int wantedCount, int actualCount, DescribedInvocation wanted,
+                                                          Location firstUndesired) {
+        return join(
+                wanted.toString(),
+                "Wanted " + pluralize(wantedCount) + ":",
+                new LocationImpl(),
+                "But was " + pluralize(actualCount) + ". Undesired invocation:",
+                firstUndesired,
+                ""
+        );
+    }
+
+    public static MockitoAssertionError neverWantedButInvoked(DescribedInvocation wanted, Location firstUndesired) {
+        return new NeverWantedButInvoked(join(
+                wanted.toString(),
+                "Never wanted here:",
+                new LocationImpl(),
+                "But invoked here:",
+                firstUndesired,
+                ""
+        ));
+    }
+
+    public static MockitoAssertionError tooManyActualInvocationsInOrder(int wantedCount, int actualCount, DescribedInvocation wanted, Location firstUndesired) {
+        String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, firstUndesired);
+        return new VerificationInOrderFailure(join(
+                "Verification in order failure:" + message
+        ));
+    }
+
+    private static String createTooLittleInvocationsMessage(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted,
+                                                            Location lastActualInvocation) {
+        String ending =
+                (lastActualInvocation != null) ? lastActualInvocation + "\n" : "\n";
+
+        return join(
+                wanted.toString(),
+                "Wanted " + discrepancy.getPluralizedWantedCount() + (discrepancy.getWantedCount() == 0 ? "." : ":"),
+                new LocationImpl(),
+                "But was " + discrepancy.getPluralizedActualCount() + (discrepancy.getActualCount() == 0 ? "." : ":"),
+                ending
+        );
+    }
+
+    public static MockitoAssertionError tooLittleActualInvocations(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, Location lastActualLocation) {
+        String message = createTooLittleInvocationsMessage(discrepancy, wanted, lastActualLocation);
+
+        return new TooLittleActualInvocations(message);
+    }
+
+    public static MockitoAssertionError tooLittleActualInvocationsInOrder(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, Location lastActualLocation) {
+        String message = createTooLittleInvocationsMessage(discrepancy, wanted, lastActualLocation);
+
+        return new VerificationInOrderFailure(join(
+                "Verification in order failure:" + message
+        ));
+    }
+
+    public static MockitoAssertionError noMoreInteractionsWanted(Invocation undesired, List<VerificationAwareInvocation> invocations) {
+        ScenarioPrinter scenarioPrinter = new ScenarioPrinter();
+        String scenario = scenarioPrinter.print(invocations);
+
+        return new NoInteractionsWanted(join(
+                "No interactions wanted here:",
+                new LocationImpl(),
+                "But found this interaction on mock '" + safelyGetMockName(undesired.getMock()) + "':",
+                undesired.getLocation(),
+                scenario
+        ));
+    }
+
+    public static MockitoAssertionError noMoreInteractionsWantedInOrder(Invocation undesired) {
+        return new VerificationInOrderFailure(join(
+                "No interactions wanted here:",
+                new LocationImpl(),
+                "But found this interaction on mock '" + safelyGetMockName(undesired.getMock()) + "':",
+                undesired.getLocation()
+        ));
+    }
+
+    public static MockitoException cannotMockClass(Class<?> clazz, String reason) {
+        return new MockitoException(join(
+                "Cannot mock/spy " + clazz.toString(),
+                "Mockito cannot mock/spy because :",
+                " - " + reason
+        ));
+    }
+
+    public static MockitoException cannotStubVoidMethodWithAReturnValue(String methodName) {
+        return new CannotStubVoidMethodWithReturnValue(join(
+                "'" + methodName + "' is a *void method* and it *cannot* be stubbed with a *return value*!",
+                "Voids are usually stubbed with Throwables:",
+                "    doThrow(exception).when(mock).someVoidMethod();",
+                "***",
+                "If you're unsure why you're getting above error read on.",
+                "Due to the nature of the syntax above problem might occur because:",
+                "1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.",
+                "2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.",
+                "3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
+                "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
+                "4. " + MockitoLimitations.NON_PUBLIC_PARENT,
+                ""
+        ));
+    }
+
+    public static MockitoException onlyVoidMethodsCanBeSetToDoNothing() {
+        return new MockitoException(join(
+                "Only void methods can doNothing()!",
+                "Example of correct use of doNothing():",
+                "    doNothing().",
+                "    doThrow(new RuntimeException())",
+                "    .when(mock).someVoidMethod();",
+                "Above means:",
+                "someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called"
+        ));
+    }
+
+    public static MockitoException wrongTypeOfReturnValue(String expectedType, String actualType, String methodName) {
+        return new WrongTypeOfReturnValue(join(
+                actualType + " cannot be returned by " + methodName + "()",
+                methodName + "() should return " + expectedType,
+                "***",
+                "If you're unsure why you're getting above error read on.",
+                "Due to the nature of the syntax above problem might occur because:",
+                "1. This exception *might* occur in wrongly written multi-threaded tests.",
+                "   Please refer to Mockito FAQ on limitations of concurrency testing.",
+                "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
+                "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
+                ""
+        ));
+    }
+
+    public static MockitoException wrongTypeReturnedByDefaultAnswer(Object mock, String expectedType, String actualType, String methodName) {
+        return new WrongTypeOfReturnValue(join(
+                "Default answer returned a result with the wrong type:",
+                actualType + " cannot be returned by " + methodName + "()",
+                methodName + "() should return " + expectedType,
+                "",
+                "The default answer of " + safelyGetMockName(mock) + " that was configured on the mock is probably incorrectly implemented.",
+                ""
+        ));
+    }
+
+
+    public static MockitoAssertionError wantedAtMostX(int maxNumberOfInvocations, int foundSize) {
+        return new MockitoAssertionError(join("Wanted at most " + pluralize(maxNumberOfInvocations) + " but was " + foundSize));
+    }
+
+    public static MockitoException misplacedArgumentMatcher(List<LocalizedMatcher> lastMatchers) {
+        return new InvalidUseOfMatchersException(join(
+                "Misplaced or misused argument matcher detected here:",
+                locationsOf(lastMatchers),
+                "",
+                "You cannot use argument matchers outside of verification or stubbing.",
+                "Examples of correct usage of argument matchers:",
+                "    when(mock.get(anyInt())).thenReturn(null);",
+                "    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());",
+                "    verify(mock).someMethod(contains(\"foo\"))",
+                "",
+                "This message may appear after an NullPointerException if the last matcher is returning an object ",
+                "like any() but the stubbed method signature expect a primitive argument, in this case,",
+                "use primitive alternatives.",
+                "    when(mock.get(any())); // bad use, will raise NPE",
+                "    when(mock.get(anyInt())); // correct usage use",
+                "",
+                "Also, this error might show up because you use argument matchers with methods that cannot be mocked.",
+                "Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().",
+                MockitoLimitations.NON_PUBLIC_PARENT,
+                ""
+        ));
+    }
+
+    public static MockitoException smartNullPointerException(String invocation, Location location) {
+        return new SmartNullPointerException(join(
+                "You have a NullPointerException here:",
+                new LocationImpl(),
+                "because this method call was *not* stubbed correctly:",
+                location,
+                invocation,
+                ""
+        ));
+    }
+
+    public static MockitoException noArgumentValueWasCaptured() {
+        return new MockitoException(join(
+                "No argument value was captured!",
+                "You might have forgotten to use argument.capture() in verify()...",
+                "...or you used capture() in stubbing but stubbed method was not called.",
+                "Be aware that it is recommended to use capture() only with verify()",
+                "",
+                "Examples of correct argument capturing:",
+                "    ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);",
+                "    verify(mock).doSomething(argument.capture());",
+                "    assertEquals(\"John\", argument.getValue().getName());",
+                ""
+        ));
+    }
+
+    public static MockitoException extraInterfacesDoesNotAcceptNullParameters() {
+        return new MockitoException(join(
+                "extraInterfaces() does not accept null parameters."
+        ));
+    }
+
+    public static MockitoException extraInterfacesAcceptsOnlyInterfaces(Class<?> wrongType) {
+        return new MockitoException(join(
+                "extraInterfaces() accepts only interfaces.",
+                "You passed following type: " + wrongType.getSimpleName() + " which is not an interface."
+        ));
+    }
+
+    public static MockitoException extraInterfacesCannotContainMockedType(Class<?> wrongType) {
+        return new MockitoException(join(
+                "extraInterfaces() does not accept the same type as the mocked type.",
+                "You mocked following type: " + wrongType.getSimpleName(),
+                "and you passed the same very interface to the extraInterfaces()"
+        ));
+    }
+
+    public static MockitoException extraInterfacesRequiresAtLeastOneInterface() {
+        return new MockitoException(join(
+                "extraInterfaces() requires at least one interface."
+        ));
+    }
+
+    public static MockitoException mockedTypeIsInconsistentWithSpiedInstanceType(Class<?> mockedType, Object spiedInstance) {
+        return new MockitoException(join(
+                "Mocked type must be the same as the type of your spied instance.",
+                "Mocked type must be: " + spiedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
+                "  //correct spying:",
+                "  spy = mock( ->ArrayList.class<- , withSettings().spiedInstance( ->new ArrayList()<- );",
+                "  //incorrect - types don't match:",
+                "  spy = mock( ->List.class<- , withSettings().spiedInstance( ->new ArrayList()<- );"
+        ));
+    }
+
+    public static MockitoException cannotCallAbstractRealMethod() {
+        return new MockitoException(join(
+                "Cannot call abstract real method on java object!",
+                "Calling real methods is only possible when mocking non abstract method.",
+                "  //correct example:",
+                "  when(mockOfConcreteClass.nonAbstractMethod()).thenCallRealMethod();"
+        ));
+    }
+
+    public static MockitoException cannotVerifyToString() {
+        return new MockitoException(join(
+                "Mockito cannot verify toString()",
+                "toString() is too often used behind of scenes  (i.e. during String concatenation, in IDE debugging views). " +
+                        "Verifying it may give inconsistent or hard to understand results. " +
+                        "Not to mention that verifying toString() most likely hints awkward design (hard to explain in a short exception message. Trust me...)",
+                "However, it is possible to stub toString(). Stubbing toString() smells a bit funny but there are rare, legitimate use cases."
+        ));
+    }
+
+    public static MockitoException moreThanOneAnnotationNotAllowed(String fieldName) {
+        return new MockitoException("You cannot have more than one Mockito annotation on a field!\n" +
+                                            "The field '" + fieldName + "' has multiple Mockito annotations.\n" +
+                                            "For info how to use annotations see examples in javadoc for MockitoAnnotations class.");
+    }
+
+    public static MockitoException unsupportedCombinationOfAnnotations(String undesiredAnnotationOne, String undesiredAnnotationTwo) {
+        return new MockitoException("This combination of annotations is not permitted on a single field:\n" +
+                                            "@" + undesiredAnnotationOne + " and @" + undesiredAnnotationTwo);
+    }
+
+    public static MockitoException cannotInitializeForSpyAnnotation(String fieldName, Exception details) {
+        return new MockitoException(join("Cannot instantiate a @Spy for '" + fieldName + "' field.",
+                                         "You haven't provided the instance for spying at field declaration so I tried to construct the instance.",
+                                         "However, I failed because: " + details.getMessage(),
+                                         "Examples of correct usage of @Spy:",
+                                         "   @Spy List mock = new LinkedList();",
+                                         "   @Spy Foo foo; //only if Foo has parameterless constructor",
+                                         "   //also, don't forget about MockitoAnnotations.initMocks();",
+                                         ""), details);
+    }
+
+    public static MockitoException cannotInitializeForInjectMocksAnnotation(String fieldName, String causeMessage) {
+        return new MockitoException(join("Cannot instantiate @InjectMocks field named '" + fieldName + "'! Cause: "+causeMessage,
+                                         "You haven't provided the instance at field declaration so I tried to construct the instance.",
+                                         "Examples of correct usage of @InjectMocks:",
+                                         "   @InjectMocks Service service = new Service();",
+                                         "   @InjectMocks Service service;",
+                                         "   //and... don't forget about some @Mocks for injection :)",
+                                         ""));
+    }
+
+    public static MockitoException atMostAndNeverShouldNotBeUsedWithTimeout() {
+        return new FriendlyReminderException(join("",
+                                                  "Don't panic! I'm just a friendly reminder!",
+                                                  "timeout() should not be used with atMost() or never() because...",
+                                                  "...it does not make much sense - the test would have passed immediately in concurency",
+                                                  "We kept this method only to avoid compilation errors when upgrading Mockito.",
+                                                  "In future release we will remove timeout(x).atMost(y) from the API.",
+                                                  "If you want to find out more please refer to issue 235",
+                                                  ""));
+    }
+
+    public static MockitoException fieldInitialisationThrewException(Field field, Throwable details) {
+        return new MockitoException(join(
+                "Cannot instantiate @InjectMocks field named '" + field.getName() + "' of type '" + field.getType() + "'.",
+                "You haven't provided the instance at field declaration so I tried to construct the instance.",
+                "However the constructor or the initialization block threw an exception : " + details.getMessage(),
+                ""), details);
+
+    }
+
+    public static MockitoException invocationListenerDoesNotAcceptNullParameters() {
+        return new MockitoException("invocationListeners() does not accept null parameters");
+    }
+
+    public static MockitoException invocationListenersRequiresAtLeastOneListener() {
+        return new MockitoException("invocationListeners() requires at least one listener");
+    }
+
+    public static MockitoException invocationListenerThrewException(InvocationListener listener, Throwable listenerThrowable) {
+        return new MockitoException(join(
+                "The invocation listener with type " + listener.getClass().getName(),
+                "threw an exception : " + listenerThrowable.getClass().getName() + listenerThrowable.getMessage()), listenerThrowable);
+    }
+
+    public static MockitoException cannotInjectDependency(Field field, Object matchingMock, Exception details) {
+        return new MockitoException(join(
+                "Mockito couldn't inject mock dependency '" + safelyGetMockName(matchingMock) + "' on field ",
+                "'" + field + "'",
+                "whose type '" + field.getDeclaringClass().getCanonicalName() + "' was annotated by @InjectMocks in your test.",
+                "Also I failed because: " + exceptionCauseMessageIfAvailable(details),
+                ""
+        ), details);
+    }
+
+    private static String exceptionCauseMessageIfAvailable(Exception details) {
+        if (details.getCause() == null) {
+            return details.getMessage();
+        }
+        return details.getCause().getMessage();
+    }
+
+    public static MockitoException mockedTypeIsInconsistentWithDelegatedInstanceType(Class<?> mockedType, Object delegatedInstance) {
+        return new MockitoException(join(
+                "Mocked type must be the same as the type of your delegated instance.",
+                "Mocked type must be: " + delegatedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
+                "  //correct delegate:",
+                "  spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new ArrayList()<- );",
+                "  //incorrect - types don't match:",
+                "  spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new HashSet()<- );"
+        ));
+    }
+
+    public static MockitoException spyAndDelegateAreMutuallyExclusive() {
+        return new MockitoException(join(
+                "Settings should not define a spy instance and a delegated instance at the same time."
+        ));
+    }
+
+    public static MockitoException invalidArgumentRangeAtIdentityAnswerCreationTime() {
+        return new MockitoException(join(
+                "Invalid argument index.",
+                "The index need to be a positive number that indicates the position of the argument to return.",
+                "However it is possible to use the -1 value to indicates that the last argument should be",
+                "returned."));
+    }
+
+    public static MockitoException invalidArgumentPositionRangeAtInvocationTime(InvocationOnMock invocation, boolean willReturnLastParameter, int argumentIndex) {
+        return new MockitoException(join(
+                "Invalid argument index for the current invocation of method : ",
+                " -> " + safelyGetMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
+                "",
+                (willReturnLastParameter ?
+                        "Last parameter wanted" :
+                        "Wanted parameter at position " + argumentIndex) + " but " + possibleArgumentTypesOf(invocation),
+                "The index need to be a positive number that indicates a valid position of the argument in the invocation.",
+                "However it is possible to use the -1 value to indicates that the last argument should be returned.",
+                ""
+        ));
+    }
+
+    private static StringBuilder possibleArgumentTypesOf(InvocationOnMock invocation) {
+        Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
+        if (parameterTypes.length == 0) {
+            return new StringBuilder("the method has no arguments.\n");
+        }
+
+        StringBuilder stringBuilder = new StringBuilder("the possible argument indexes for this method are :\n");
+        for (int i = 0, parameterTypesLength = parameterTypes.length; i < parameterTypesLength; i++) {
+            stringBuilder.append("    [").append(i);
+
+            if (invocation.getMethod().isVarArgs() && i == parameterTypesLength - 1) {
+                stringBuilder.append("+] ").append(parameterTypes[i].getComponentType().getSimpleName()).append("  <- Vararg").append("\n");
+            } else {
+                stringBuilder.append("] ").append(parameterTypes[i].getSimpleName()).append("\n");
+            }
+        }
+        return stringBuilder;
+    }
+
+    public static MockitoException wrongTypeOfArgumentToReturn(InvocationOnMock invocation, String expectedType, Class<?> actualType, int argumentIndex) {
+        return new WrongTypeOfReturnValue(join(
+                "The argument of type '" + actualType.getSimpleName() + "' cannot be returned because the following ",
+                "method should return the type '" + expectedType + "'",
+                " -> " + safelyGetMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
+                "",
+                "The reason for this error can be :",
+                "1. The wanted argument position is incorrect.",
+                "2. The answer is used on the wrong interaction.",
+                "",
+                "Position of the wanted argument is " + argumentIndex + " and " + possibleArgumentTypesOf(invocation),
+                "***",
+                "However if you're still unsure why you're getting above error read on.",
+                "Due to the nature of the syntax above problem might occur because:",
+                "1. This exception *might* occur in wrongly written multi-threaded tests.",
+                "   Please refer to Mockito FAQ on limitations of concurrency testing.",
+                "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
+                "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
+                ""
+        ));
+    }
+
+    public static MockitoException defaultAnswerDoesNotAcceptNullParameter() {
+        return new MockitoException("defaultAnswer() does not accept null parameter");
+    }
+
+    public static MockitoException serializableWontWorkForObjectsThatDontImplementSerializable(Class<?> classToMock) {
+        return new MockitoException(join(
+                "You are using the setting 'withSettings().serializable()' however the type you are trying to mock '" + classToMock.getSimpleName() + "'",
+                "do not implement Serializable AND do not have a no-arg constructor.",
+                "This combination is requested, otherwise you will get an 'java.io.InvalidClassException' when the mock will be serialized",
+                "",
+                "Also note that as requested by the Java serialization specification, the whole hierarchy need to implements Serializable,",
+                "i.e. the top-most superclass has to implements Serializable.",
+                ""
+        ));
+    }
+
+    public static MockitoException delegatedMethodHasWrongReturnType(Method mockMethod, Method delegateMethod, Object mock, Object delegate) {
+        return new MockitoException(join(
+                "Methods called on delegated instance must have compatible return types with the mock.",
+                "When calling: " + mockMethod + " on mock: " + safelyGetMockName(mock),
+                "return type should be: " + mockMethod.getReturnType().getSimpleName() + ", but was: " + delegateMethod.getReturnType().getSimpleName(),
+                "Check that the instance passed to delegatesTo() is of the correct type or contains compatible methods",
+                "(delegate instance had type: " + delegate.getClass().getSimpleName() + ")"
+        ));
+    }
+
+    public static MockitoException delegatedMethodDoesNotExistOnDelegate(Method mockMethod, Object mock, Object delegate) {
+        return new MockitoException(join(
+                "Methods called on mock must exist in delegated instance.",
+                "When calling: " + mockMethod + " on mock: " + safelyGetMockName(mock),
+                "no such method was found.",
+                "Check that the instance passed to delegatesTo() is of the correct type or contains compatible methods",
+                "(delegate instance had type: " + delegate.getClass().getSimpleName() + ")"
+        ));
+    }
+
+    public static MockitoException usingConstructorWithFancySerializable(SerializableMode mode) {
+        return new MockitoException("Mocks instantiated with constructor cannot be combined with " + mode + " serialization mode.");
+    }
+
+    public static MockitoException cannotCreateTimerWithNegativeDurationTime(long durationMillis) {
+        return new FriendlyReminderException(join(
+                "",
+                "Don't panic! I'm just a friendly reminder!",
+                "It is impossible for time to go backward, therefore...",
+                "You cannot put negative value of duration: (" + durationMillis + ")",
+                "as argument of timer methods (after(), timeout())",
+                ""
+        ));
+    }
+
+    public static MockitoException notAnException() {
+        return new MockitoException(join(
+                "Exception type cannot be null.",
+                "This may happen with doThrow(Class)|thenThrow(Class) family of methods if passing null parameter."));
+    }
+
+    private static MockName safelyGetMockName(Object mock) {
+        return MockUtil.getMockName(mock);
+    }
+
+    public static UnnecessaryStubbingException formatUnncessaryStubbingException(Class<?> testClass, Collection<Invocation> unnecessaryStubbings) {
+        StringBuilder stubbings = new StringBuilder();
+        int count = 1;
+        for (Invocation u : unnecessaryStubbings) {
+            stubbings.append("\n  ").append(count++).append(". ").append(u.getLocation());
+        }
+        String heading = (testClass != null)?
+                "Unnecessary stubbings detected in test class: " + testClass.getSimpleName() :
+                "Unnecessary stubbings detected.";
+
+        return new UnnecessaryStubbingException(join(
+                heading,
+                "Clean & maintainable test code requires zero unnecessary code.",
+                "Following stubbings are unnecessary (click to navigate to relevant line of code):" + stubbings,
+                "Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class."
+        ));
+    }
+
+    public static void unncessaryStubbingException(List<Invocation> unused) {
+        throw formatUnncessaryStubbingException(null, unused);
+    }
+
+    public static void potentialStubbingProblem(
+            Invocation actualInvocation, Collection<Invocation> argMismatchStubbings) {
+        StringBuilder stubbings = new StringBuilder();
+        int count = 1;
+        for (Invocation s : argMismatchStubbings) {
+            stubbings.append("    ").append(count++).append(". ").append(s);
+            stubbings.append("\n      ").append(s.getLocation()).append("\n");
+        }
+        stubbings.deleteCharAt(stubbings.length()-1); //remove trailing end of line
+
+        throw new PotentialStubbingProblem(join(
+                "Strict stubbing argument mismatch. Please check:",
+                " - this invocation of '" + actualInvocation.getMethod().getName() + "' method:",
+                "    " + actualInvocation,
+                "    " + actualInvocation.getLocation(),
+                " - has following stubbing(s) with different arguments:",
+                stubbings,
+                "Typically, stubbing argument mismatch indicates user mistake when writing tests.",
+                "Mockito fails early so that you can debug potential problem easily.",
+                "However, there are legit scenarios when this exception generates false negative signal:",
+                "  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API",
+                "    Please use 'will().given()' or 'doReturn().when()' API for stubbing.",
+                "  - stubbed method is intentionally invoked with different arguments by code under test",
+                "    Please use 'default' or 'silent' JUnit Rule.",
+                "For more information see javadoc for PotentialStubbingProblem class."));
+    }
+
+    public static void redundantMockitoListener(String listenerType) {
+        throw new RedundantListenerException(join(
+            "Problems adding Mockito listener.",
+            "Listener of type '" + listenerType + "' has already been added and not removed.",
+            "It indicates that previous listener was not removed according to the API.",
+            "When you add a listener, don't forget to remove the listener afterwards:",
+            "  Mockito.framework().removeListener(myListener);",
+            "For more information, see the javadoc for RedundantListenerException class."));
+    }
+
+    public static void unfinishedMockingSession() {
+        throw new UnfinishedMockingSessionException(join(
+                "Unfinished mocking session detected.",
+                "Previous MockitoSession was not concluded with 'finishMocking()'.",
+                "For examples of correct usage see javadoc for MockitoSession class."));
+    }
+}
diff --git a/src/main/java/org/mockito/internal/exceptions/VerificationAwareInvocation.java b/src/main/java/org/mockito/internal/exceptions/VerificationAwareInvocation.java
index adfdbc9..9920aa6 100644
--- a/src/main/java/org/mockito/internal/exceptions/VerificationAwareInvocation.java
+++ b/src/main/java/org/mockito/internal/exceptions/VerificationAwareInvocation.java
@@ -8,7 +8,7 @@
 import org.mockito.invocation.DescribedInvocation;
 
 public interface VerificationAwareInvocation extends DescribedInvocation {
-    
+
     boolean isVerified();
-    
-}
\ No newline at end of file
+
+}
diff --git a/src/main/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java b/src/main/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java
index 1996e40..c0d1150 100644
--- a/src/main/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java
+++ b/src/main/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java
@@ -12,10 +12,10 @@
 
 public class ConditionalStackTraceFilter implements Serializable {
     private static final long serialVersionUID = -8085849703510292641L;
-    
+
     private final IMockitoConfiguration config = new GlobalConfiguration();
     private final StackTraceFilter filter = new StackTraceFilter();
-    
+
     public void filter(Throwable throwable) {
         if (!config.cleansStackTrace()) {
             return;
@@ -23,4 +23,4 @@
         StackTraceElement[] filtered = filter.filter(throwable.getStackTrace(), true);
         throwable.setStackTrace(filtered);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java b/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java
index 84727c9..6f7b956 100644
--- a/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java
+++ b/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java
@@ -1,16 +1,42 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.exceptions.stacktrace;
 
 import org.mockito.exceptions.stacktrace.StackTraceCleaner;
 
 /**
-* by Szczepan Faber, created at: 7/29/12
-*/
+ * This predicate is used to filter "good" {@link StackTraceElement}. Good
+ */
 public class DefaultStackTraceCleaner implements StackTraceCleaner {
-    public boolean isOut(StackTraceElement e) {
-        boolean fromMockObject = e.getClassName().contains("$$EnhancerByMockitoWithCGLIB$$");
-        boolean fromOrgMockito = e.getClassName().startsWith("org.mockito.");
-        boolean isRunner = e.getClassName().startsWith("org.mockito.runners.");
-        boolean isInternalRunner = e.getClassName().startsWith("org.mockito.internal.runners.");
-        return (fromMockObject || fromOrgMockito) && !isRunner && !isInternalRunner;
+
+    @Override
+    public boolean isIn(StackTraceElement e) {
+        if (isFromMockitoRunner(e.getClassName()) || isFromMockitoRule(e.getClassName())) {
+            return true;
+        } else if (isMockDispatcher(e.getClassName()) || isFromMockito(e.getClassName())) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    private static boolean isMockDispatcher(String className) {
+        return (className.contains("$$EnhancerByMockitoWithCGLIB$$") || className.contains("$MockitoMock$"));
+    }
+
+    private static boolean isFromMockito(String className) {
+        return className.startsWith("org.mockito.");
+    }
+
+    private static boolean isFromMockitoRule(String className) {
+        return className.startsWith("org.mockito.internal.junit.JUnitRule");
+    }
+
+    private static boolean isFromMockitoRunner(String className) {
+        return className.startsWith("org.mockito.internal.runners.")
+               || className.startsWith("org.mockito.runners.")
+               || className.startsWith("org.mockito.junit.");
     }
 }
diff --git a/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java b/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java
index b0d30e4..ef500ce 100644
--- a/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java
+++ b/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.exceptions.stacktrace;
 
 import org.mockito.exceptions.stacktrace.StackTraceCleaner;
@@ -11,4 +15,4 @@
     public StackTraceCleaner getStackTraceCleaner(StackTraceCleaner defaultCleaner) {
         return defaultCleaner;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java b/src/main/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java
index cd462dc..e8b0cb0 100644
--- a/src/main/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java
+++ b/src/main/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java
@@ -10,8 +10,6 @@
 
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
 import java.util.List;
 
 public class StackTraceFilter implements Serializable {
@@ -20,38 +18,23 @@
 
     private static final StackTraceCleaner CLEANER =
             Plugins.getStackTraceCleanerProvider().getStackTraceCleaner(new DefaultStackTraceCleaner());
-    
+
     /**
      * Example how the filter works (+/- means good/bad):
-     * [a+, b+, c-, d+, e+, f-, g+] -> [a+, b+, g+]
-     * Basically removes all bad from the middle. If any good are in the middle of bad those are also removed. 
+     * [a+, b+, c-, d+, e+, f-, g+] -> [a+, b+, d+, e+, g+]
+     * Basically removes all bad from the middle.
+     * <strike>If any good are in the middle of bad those are also removed.</strike>
      */
     public StackTraceElement[] filter(StackTraceElement[] target, boolean keepTop) {
         //TODO: profile
-        List<StackTraceElement> unfilteredStackTrace = Arrays.asList(target);
-        
-        int lastBad = -1;
-        int firstBad = -1;
-        for (int i = 0; i < unfilteredStackTrace.size(); i++) {
-            if (!CLEANER.isOut(unfilteredStackTrace.get(i))) {
-                continue;
-            }
-            lastBad = i;
-            if (firstBad == -1) {
-                firstBad = i;
+        //TODO: investigate "keepTop" commit history - no effect!
+        final List<StackTraceElement> filtered = new ArrayList<StackTraceElement>();
+        for (StackTraceElement element : target) {
+            if (CLEANER.isIn(element)) {
+                filtered.add(element);
             }
         }
-        
-        List<StackTraceElement> top;
-        if (keepTop && firstBad != -1) {
-            top = unfilteredStackTrace.subList(0, firstBad);
-        } else {
-            top = new LinkedList<StackTraceElement>();
-        }
-        
-        List<StackTraceElement> bottom = unfilteredStackTrace.subList(lastBad + 1, unfilteredStackTrace.size());
-        List<StackTraceElement> filtered = new ArrayList<StackTraceElement>(top);
-        filtered.addAll(bottom);
-        return filtered.toArray(new StackTraceElement[]{});
+        StackTraceElement[] result = new StackTraceElement[filtered.size()];
+        return filtered.toArray(result);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/exceptions/stacktrace/package-info.java b/src/main/java/org/mockito/internal/exceptions/stacktrace/package-info.java
new file mode 100644
index 0000000..784a68f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/exceptions/stacktrace/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Stack trace filtering / cleaning internal APIs.
+ */
+package org.mockito.internal.exceptions.stacktrace;
diff --git a/src/main/java/org/mockito/internal/exceptions/stacktrace/package.html b/src/main/java/org/mockito/internal/exceptions/stacktrace/package.html
deleted file mode 100644
index 84b9ff9..0000000
--- a/src/main/java/org/mockito/internal/exceptions/stacktrace/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Stack trace filtering / cleaning internal APIs.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/exceptions/util/ScenarioPrinter.java b/src/main/java/org/mockito/internal/exceptions/util/ScenarioPrinter.java
index 82259e6..a3e60fe 100644
--- a/src/main/java/org/mockito/internal/exceptions/util/ScenarioPrinter.java
+++ b/src/main/java/org/mockito/internal/exceptions/util/ScenarioPrinter.java
@@ -2,32 +2,31 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.exceptions.util;

-

-import java.util.List;

-

-import org.mockito.internal.exceptions.VerificationAwareInvocation;

-

-public class ScenarioPrinter {

-

-    public String print(List<VerificationAwareInvocation> invocations) {

-        if (invocations.size() == 1) {

-            return "Actually, above is the only interaction with this mock.";

-        }

-        StringBuilder sb = new StringBuilder(

-                "***\n" +

-                "For your reference, here is the list of all invocations ([?] - means unverified).\n");

-        

-        int counter = 0;

-        for (VerificationAwareInvocation i : invocations) {

-            sb.append(++counter + ". ");

-            if (!i.isVerified()) {

-                sb.append("[?]");

-            }

-            sb.append(i.getLocation() + "\n");

-        }

-        String scenario = sb.toString();

-        return scenario;

-    }

-

-}

+package org.mockito.internal.exceptions.util;
+
+import java.util.List;
+
+import org.mockito.internal.exceptions.VerificationAwareInvocation;
+
+public class ScenarioPrinter {
+
+    public String print(List<VerificationAwareInvocation> invocations) {
+        if (invocations.size() == 1) {
+            return "Actually, above is the only interaction with this mock.";
+        }
+        StringBuilder sb = new StringBuilder(
+                "***\n" +
+                "For your reference, here is the list of all invocations ([?] - means unverified).\n");
+
+        int counter = 0;
+        for (VerificationAwareInvocation i : invocations) {
+            sb.append(++counter).append(". ");
+            if (!i.isVerified()) {
+                sb.append("[?]");
+            }
+            sb.append(i.getLocation()).append("\n");
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java b/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java
new file mode 100644
index 0000000..cd9f1cf
--- /dev/null
+++ b/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.framework;
+
+import org.mockito.MockitoFramework;
+import org.mockito.internal.util.Checks;
+import org.mockito.listeners.MockitoListener;
+
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
+public class DefaultMockitoFramework implements MockitoFramework {
+
+    public MockitoFramework addListener(MockitoListener listener) {
+        Checks.checkNotNull(listener, "listener");
+        mockingProgress().addListener(listener);
+        return this;
+    }
+
+    public MockitoFramework removeListener(MockitoListener listener) {
+        Checks.checkNotNull(listener, "listener");
+        mockingProgress().removeListener(listener);
+        return this;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java b/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java
new file mode 100644
index 0000000..4a32193
--- /dev/null
+++ b/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java
@@ -0,0 +1,52 @@
+package org.mockito.internal.framework;
+
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.misusing.RedundantListenerException;
+import org.mockito.internal.exceptions.Reporter;
+import org.mockito.internal.junit.TestFinishedEvent;
+import org.mockito.internal.junit.UniversalTestListener;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.quality.Strictness;
+
+public class DefaultMockitoSession implements MockitoSession {
+
+    private final Object testClassInstance;
+    private final UniversalTestListener listener;
+
+    public DefaultMockitoSession(Object testClassInstance, Strictness strictness, MockitoLogger logger) {
+        this.testClassInstance = testClassInstance;
+        listener = new UniversalTestListener(strictness, logger);
+        try {
+            //So that the listener can capture mock creation events
+            Mockito.framework().addListener(listener);
+        } catch (RedundantListenerException e) {
+            Reporter.unfinishedMockingSession();
+        }
+        MockitoAnnotations.initMocks(testClassInstance);
+    }
+
+    public void finishMocking() {
+        //Cleaning up the state, we no longer need the listener hooked up
+        //The listener implements MockCreationListener and at this point
+        //we no longer need to listen on mock creation events. We are wrapping up the session
+        Mockito.framework().removeListener(listener);
+
+        //Emit test finished event so that validation such as strict stubbing can take place
+        listener.testFinished(new TestFinishedEvent() {
+            public Throwable getFailure() {
+                return null;
+            }
+            public Object getTestClassInstance() {
+                return testClassInstance;
+            }
+            public String getTestMethodName() {
+                return null;
+            }
+        });
+
+        //Finally, validate user's misuse of Mockito framework.
+        Mockito.validateMockitoUsage();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java b/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
new file mode 100644
index 0000000..f5216ee
--- /dev/null
+++ b/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.hamcrest;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+import org.mockito.ArgumentMatcher;
+
+public class HamcrestArgumentMatcher<T> implements ArgumentMatcher<T> {
+
+    private final Matcher matcher;
+
+    public HamcrestArgumentMatcher(Matcher<T> matcher) {
+        this.matcher = matcher;
+    }
+
+    public boolean matches(Object argument) {
+        return this.matcher.matches(argument);
+    }
+
+    public String toString() {
+        //TODO SF add unit tests and integ test coverage for describeTo()
+        return StringDescription.toString(matcher);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractor.java b/src/main/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractor.java
new file mode 100644
index 0000000..f9c8806
--- /dev/null
+++ b/src/main/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractor.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.hamcrest;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Matcher;
+
+import static org.mockito.internal.util.reflection.GenericTypeExtractor.genericTypeOf;
+
+/**
+ * Extracts generic type of matcher
+ */
+public class MatcherGenericTypeExtractor {
+
+    /**
+     * Gets the generic type of given matcher. For example,
+     * for matcher class that extends BaseMatcher[Integer] this method returns Integer
+     */
+    public static Class<?> genericTypeOfMatcher(Class<?> matcherClass) {
+        //TODO SF check if we can reuse it for Mockito ArgumentMatcher
+        return genericTypeOf(matcherClass, BaseMatcher.class, Matcher.class);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/handler/InvocationNotifierHandler.java b/src/main/java/org/mockito/internal/handler/InvocationNotifierHandler.java
index 3876812..562089f 100644
--- a/src/main/java/org/mockito/internal/handler/InvocationNotifierHandler.java
+++ b/src/main/java/org/mockito/internal/handler/InvocationNotifierHandler.java
@@ -1,84 +1,78 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.handler;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.InternalMockHandler;

-import org.mockito.internal.listeners.NotifiedMethodInvocationReport;

-import org.mockito.internal.stubbing.InvocationContainer;

-import org.mockito.invocation.Invocation;

-import org.mockito.invocation.MockHandler;

-import org.mockito.listeners.InvocationListener;

-import org.mockito.mock.MockCreationSettings;

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.VoidMethodStubbable;

-

-import java.util.List;

-

-/**

- * Handler, that call all listeners wanted for this mock, before delegating it

- * to the parameterized handler.

- *

- * Also imposterize MockHandlerImpl, delegate all call of InternalMockHandler to the real mockHandler

- */

-class InvocationNotifierHandler<T> implements MockHandler, InternalMockHandler<T> {

-

-    private final List<InvocationListener> invocationListeners;

-    private final InternalMockHandler<T> mockHandler;

-

-    public InvocationNotifierHandler(InternalMockHandler<T> mockHandler, MockCreationSettings settings) {

-        this.mockHandler = mockHandler;

-        this.invocationListeners = settings.getInvocationListeners();

-    }

-

-    public Object handle(Invocation invocation) throws Throwable {

-        try {

-            Object returnedValue = mockHandler.handle(invocation);

-            notifyMethodCall(invocation, returnedValue);

-            return returnedValue;

-        } catch (Throwable t){

-            notifyMethodCallException(invocation, t);

-            throw t;

-        }

-    }

-

-

-	private void notifyMethodCall(Invocation invocation, Object returnValue) {

-		for (InvocationListener listener : invocationListeners) {

-            try {

-                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, returnValue));

-            } catch(Throwable listenerThrowable) {

-                new Reporter().invocationListenerThrewException(listener, listenerThrowable);

-            }

-        }

-	}

-

-    private void notifyMethodCallException(Invocation invocation, Throwable exception) {

-		for (InvocationListener listener : invocationListeners) {

-            try {

-                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, exception));

-            } catch(Throwable listenerThrowable) {

-                new Reporter().invocationListenerThrewException(listener, listenerThrowable);

-            }

-        }

-	}

-

-    public MockCreationSettings getMockSettings() {

-        return mockHandler.getMockSettings();

-    }

-

-    public VoidMethodStubbable<T> voidMethodStubbable(T mock) {

-        return mockHandler.voidMethodStubbable(mock);

-    }

-

-    public void setAnswersForStubbing(List<Answer> answers) {

-        mockHandler.setAnswersForStubbing(answers);

-    }

-

-    public InvocationContainer getInvocationContainer() {

-        return mockHandler.getInvocationContainer();

-    }

-

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import static org.mockito.internal.exceptions.Reporter.invocationListenerThrewException;
+
+import java.util.List;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Handler, that call all listeners wanted for this mock, before delegating it
+ * to the parameterized handler.
+ *
+ * Also imposterize MockHandlerImpl, delegate all call of InternalMockHandler to the real mockHandler
+ */
+class InvocationNotifierHandler<T> implements MockHandler, InternalMockHandler<T> {
+
+    private final List<InvocationListener> invocationListeners;
+    private final InternalMockHandler<T> mockHandler;
+
+    public InvocationNotifierHandler(InternalMockHandler<T> mockHandler, MockCreationSettings<T> settings) {
+        this.mockHandler = mockHandler;
+        this.invocationListeners = settings.getInvocationListeners();
+    }
+
+    public Object handle(Invocation invocation) throws Throwable {
+        try {
+            Object returnedValue = mockHandler.handle(invocation);
+            notifyMethodCall(invocation, returnedValue);
+            return returnedValue;
+        } catch (Throwable t){
+            notifyMethodCallException(invocation, t);
+            throw t;
+        }
+    }
+
+
+    private void notifyMethodCall(Invocation invocation, Object returnValue) {
+        for (InvocationListener listener : invocationListeners) {
+            try {
+                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, returnValue));
+            } catch(Throwable listenerThrowable) {
+                throw invocationListenerThrewException(listener, listenerThrowable);
+            }
+        }
+    }
+
+    private void notifyMethodCallException(Invocation invocation, Throwable exception) {
+        for (InvocationListener listener : invocationListeners) {
+            try {
+                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, exception));
+            } catch(Throwable listenerThrowable) {
+                throw invocationListenerThrewException(listener, listenerThrowable);
+            }
+        }
+    }
+
+    public MockCreationSettings<T> getMockSettings() {
+        return mockHandler.getMockSettings();
+    }
+
+    public void setAnswersForStubbing(List<Answer<?>> answers) {
+        mockHandler.setAnswersForStubbing(answers);
+    }
+
+    public InvocationContainer getInvocationContainer() {
+        return mockHandler.getInvocationContainer();
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/handler/MockHandlerFactory.java b/src/main/java/org/mockito/internal/handler/MockHandlerFactory.java
index 4fef71b..0d11243 100644
--- a/src/main/java/org/mockito/internal/handler/MockHandlerFactory.java
+++ b/src/main/java/org/mockito/internal/handler/MockHandlerFactory.java
@@ -12,11 +12,9 @@
  */
 public class MockHandlerFactory {
 
-    public InternalMockHandler create(MockCreationSettings settings) {
-        InternalMockHandler handler = new MockHandlerImpl(settings);
-        InternalMockHandler nullResultGuardian = new NullResultGuardian(handler);
-        InternalMockHandler notifier = new InvocationNotifierHandler(nullResultGuardian, settings);
-
-        return notifier;
+    public static <T> InternalMockHandler<T> createMockHandler(MockCreationSettings<T> settings) {
+        InternalMockHandler<T> handler = new MockHandlerImpl<T>(settings);
+        InternalMockHandler<T> nullResultGuardian = new NullResultGuardian<T>(handler);
+        return new InvocationNotifierHandler<T>(nullResultGuardian, settings);
     }
 }
diff --git a/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java b/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java
index a49c1a9..3ef887c 100644
--- a/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java
+++ b/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java
@@ -4,64 +4,67 @@
  */
 package org.mockito.internal.handler;
 
-import org.mockito.exceptions.Reporter;
+import java.util.List;
 import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.settings.CreationSettings;
 import org.mockito.internal.invocation.InvocationMatcher;
 import org.mockito.internal.invocation.MatchersBinder;
-import org.mockito.internal.progress.MockingProgress;
-import org.mockito.internal.progress.ThreadSafeMockingProgress;
-import org.mockito.internal.stubbing.*;
+import org.mockito.internal.listeners.StubbingLookupListener;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.stubbing.InvocationContainerImpl;
+import org.mockito.internal.stubbing.OngoingStubbingImpl;
+import org.mockito.internal.stubbing.StubbedInvocationMatcher;
+import org.mockito.internal.stubbing.answers.DefaultAnswerValidator;
 import org.mockito.internal.verification.MockAwareVerificationMode;
 import org.mockito.internal.verification.VerificationDataImpl;
 import org.mockito.invocation.Invocation;
 import org.mockito.mock.MockCreationSettings;
 import org.mockito.stubbing.Answer;
-import org.mockito.stubbing.VoidMethodStubbable;
 import org.mockito.verification.VerificationMode;
 
-import java.util.List;
+import static org.mockito.internal.exceptions.Reporter.stubPassedToVerify;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
 
 /**
  * Invocation handler set on mock objects.
- * 
- * @param <T>
- *            type of mock object to handle
+ *
+ * @param <T> type of mock object to handle
  */
-class MockHandlerImpl<T> implements InternalMockHandler<T> {
+public class MockHandlerImpl<T> implements InternalMockHandler<T> {
 
     private static final long serialVersionUID = -2917871070982574165L;
 
     InvocationContainerImpl invocationContainerImpl;
+
     MatchersBinder matchersBinder = new MatchersBinder();
-    MockingProgress mockingProgress = new ThreadSafeMockingProgress();
 
-    private final MockCreationSettings mockSettings;
+    private final MockCreationSettings<T> mockSettings;
 
-    public MockHandlerImpl(MockCreationSettings mockSettings) {
+    public MockHandlerImpl(MockCreationSettings<T> mockSettings) {
         this.mockSettings = mockSettings;
-        this.mockingProgress = new ThreadSafeMockingProgress();
+
         this.matchersBinder = new MatchersBinder();
-        this.invocationContainerImpl = new InvocationContainerImpl(mockingProgress, mockSettings);
+        this.invocationContainerImpl = new InvocationContainerImpl( mockSettings);
     }
 
     public Object handle(Invocation invocation) throws Throwable {
-		if (invocationContainerImpl.hasAnswersForStubbing()) {
-            // stubbing voids with stubVoid() or doAnswer() style
+        if (invocationContainerImpl.hasAnswersForStubbing()) {
+            // stubbing voids with doThrow() or doAnswer() style
             InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(
-                    mockingProgress.getArgumentMatcherStorage(),
+                    mockingProgress().getArgumentMatcherStorage(),
                     invocation
             );
             invocationContainerImpl.setMethodForStubbing(invocationMatcher);
             return null;
         }
-        VerificationMode verificationMode = mockingProgress.pullVerificationMode();
+        VerificationMode verificationMode = mockingProgress().pullVerificationMode();
 
         InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(
-                mockingProgress.getArgumentMatcherStorage(),
+                mockingProgress().getArgumentMatcherStorage(),
                 invocation
         );
 
-        mockingProgress.validateState();
+        mockingProgress().validateState();
 
         // if verificationMode is not null then someone is doing verify()
         if (verificationMode != null) {
@@ -74,23 +77,25 @@
             } else {
                 // this means there is an invocation on a different mock. Re-adding verification mode
                 // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
-                mockingProgress.verificationStarted(verificationMode);
+                mockingProgress().verificationStarted(verificationMode);
             }
         }
 
         // prepare invocation for stubbing
         invocationContainerImpl.setInvocationForPotentialStubbing(invocationMatcher);
         OngoingStubbingImpl<T> ongoingStubbing = new OngoingStubbingImpl<T>(invocationContainerImpl);
-        mockingProgress.reportOngoingStubbing(ongoingStubbing);
+        mockingProgress().reportOngoingStubbing(ongoingStubbing);
 
         // look for existing answer for this invocation
         StubbedInvocationMatcher stubbedInvocation = invocationContainerImpl.findAnswerFor(invocation);
+        notifyStubbedAnswerLookup(invocation, stubbedInvocation);
 
         if (stubbedInvocation != null) {
             stubbedInvocation.captureArgumentsFrom(invocation);
             return stubbedInvocation.answer(invocation);
         } else {
-             Object ret = mockSettings.getDefaultAnswer().answer(invocation);
+            Object ret = mockSettings.getDefaultAnswer().answer(invocation);
+            DefaultAnswerValidator.validateReturnValueFor(invocation, ret);
 
             // redo setting invocation for potential stubbing in case of partial
             // mocks / spies.
@@ -100,18 +105,13 @@
             invocationContainerImpl.resetInvocationForPotentialStubbing(invocationMatcher);
             return ret;
         }
-	}
-
-    public VoidMethodStubbable<T> voidMethodStubbable(T mock) {
-        return new VoidMethodStubbableImpl<T>(mock, invocationContainerImpl);
     }
 
-    public MockCreationSettings getMockSettings() {
+    public MockCreationSettings<T> getMockSettings() {
         return mockSettings;
     }
 
-    @SuppressWarnings("unchecked")
-    public void setAnswersForStubbing(List<Answer> answers) {
+    public void setAnswersForStubbing(List<Answer<?>> answers) {
         invocationContainerImpl.setAnswersForStubbing(answers);
     }
 
@@ -121,10 +121,18 @@
 
     private VerificationDataImpl createVerificationData(InvocationContainerImpl invocationContainerImpl, InvocationMatcher invocationMatcher) {
         if (mockSettings.isStubOnly()) {
-            new Reporter().stubPassedToVerify();     // this throws an exception
+            throw stubPassedToVerify();     // this throws an exception
         }
 
         return new VerificationDataImpl(invocationContainerImpl, invocationMatcher);
     }
+
+    private void notifyStubbedAnswerLookup(Invocation invocation, StubbedInvocationMatcher exception) {
+        //TODO #793 - when completed, we should be able to get rid of the casting below
+        List<StubbingLookupListener> listeners = ((CreationSettings) mockSettings).getStubbingLookupListeners();
+        for (StubbingLookupListener listener : listeners) {
+            listener.onStubbingLookup(invocation, exception);
+        }
+    }
 }
 
diff --git a/src/main/java/org/mockito/internal/handler/NotifiedMethodInvocationReport.java b/src/main/java/org/mockito/internal/handler/NotifiedMethodInvocationReport.java
new file mode 100644
index 0000000..1684f9b
--- /dev/null
+++ b/src/main/java/org/mockito/internal/handler/NotifiedMethodInvocationReport.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Invocation;
+import org.mockito.listeners.MethodInvocationReport;
+
+import static org.mockito.internal.matchers.Equality.areEqual;
+
+/**
+ * Report on a method call
+ */
+public class NotifiedMethodInvocationReport implements MethodInvocationReport {
+    private final Invocation invocation;
+    private final Object returnedValue;
+    private final Throwable throwable;
+
+
+    /**
+     * Build a new {@link org.mockito.listeners.MethodInvocationReport} with a return value.
+     *
+     *
+     * @param invocation Information on the method call
+     * @param returnedValue The value returned by the method invocation
+     */
+    public NotifiedMethodInvocationReport(Invocation invocation, Object returnedValue) {
+        this.invocation = invocation;
+        this.returnedValue = returnedValue;
+        this.throwable = null;
+    }
+
+    /**
+     * Build a new {@link org.mockito.listeners.MethodInvocationReport} with a return value.
+     *
+     *
+     * @param invocation Information on the method call
+     * @param throwable Tha throwable raised by the method invocation
+     */
+    public NotifiedMethodInvocationReport(Invocation invocation, Throwable throwable) {
+        this.invocation = invocation;
+        this.returnedValue = null;
+        this.throwable = throwable;
+    }
+
+    public DescribedInvocation getInvocation() {
+        return invocation;
+    }
+
+    public Object getReturnedValue() {
+        return returnedValue;
+    }
+
+    public Throwable getThrowable() {
+        return throwable;
+    }
+
+    public boolean threwException() {
+        return throwable != null;
+    }
+
+    public String getLocationOfStubbing() {
+        return (invocation.stubInfo() == null) ? null : invocation.stubInfo().stubbedAt().toString();
+    }
+
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        NotifiedMethodInvocationReport that = (NotifiedMethodInvocationReport) o;
+
+        return areEqual(invocation, that.invocation) &&
+               areEqual(returnedValue, that.returnedValue) &&
+               areEqual(throwable, that.throwable);
+    }
+
+    public int hashCode() {
+        int result = invocation != null ? invocation.hashCode() : 0;
+        result = 31 * result + (returnedValue != null ? returnedValue.hashCode() : 0);
+        result = 31 * result + (throwable != null ? throwable.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/handler/NullResultGuardian.java b/src/main/java/org/mockito/internal/handler/NullResultGuardian.java
index 30b03df..9fb4d14 100644
--- a/src/main/java/org/mockito/internal/handler/NullResultGuardian.java
+++ b/src/main/java/org/mockito/internal/handler/NullResultGuardian.java
@@ -4,52 +4,51 @@
  */
 package org.mockito.internal.handler;
 
+import static org.mockito.internal.util.Primitives.defaultValue;
+
+import java.util.List;
+
 import org.mockito.internal.InternalMockHandler;
-import org.mockito.internal.progress.HandyReturnValues;
 import org.mockito.internal.stubbing.InvocationContainer;
 import org.mockito.invocation.Invocation;
 import org.mockito.mock.MockCreationSettings;
-import org.mockito.stubbing.VoidMethodStubbable;
-
-import java.util.List;
+import org.mockito.stubbing.Answer;
 
 /**
  * Protects the results from delegate MockHandler. Makes sure the results are valid.
  *
  * by Szczepan Faber, created at: 5/22/12
  */
-class NullResultGuardian implements InternalMockHandler {
-    private final InternalMockHandler delegate;
+class NullResultGuardian<T> implements InternalMockHandler<T> {
 
-    public NullResultGuardian(InternalMockHandler delegate) {
+    private final InternalMockHandler<T> delegate;
+
+    public NullResultGuardian(InternalMockHandler<T> delegate) {
         this.delegate = delegate;
     }
 
+    @Override
     public Object handle(Invocation invocation) throws Throwable {
         Object result = delegate.handle(invocation);
         Class<?> returnType = invocation.getMethod().getReturnType();
         if(result == null && returnType.isPrimitive()) {
             //primitive values cannot be null
-            return new HandyReturnValues().returnFor(returnType);
-        } else {
-            return result;
+            return defaultValue(returnType);
         }
-    }
+        return result;
+     }
 
-    //boring delegation:
-
-    public MockCreationSettings getMockSettings() {
+    @Override
+    public MockCreationSettings<T> getMockSettings() {
         return delegate.getMockSettings();
     }
 
-    public VoidMethodStubbable voidMethodStubbable(Object mock) {
-        return delegate.voidMethodStubbable(mock);
+    @Override
+    public void setAnswersForStubbing(List<Answer<?>> answers) {
+            delegate.setAnswersForStubbing(answers);
     }
 
-    public void setAnswersForStubbing(List answers) {
-        delegate.setAnswersForStubbing(answers);
-    }
-
+    @Override
     public InvocationContainer getInvocationContainer() {
         return delegate.getInvocationContainer();
     }
diff --git a/src/main/java/org/mockito/internal/invocation/ArgumentMatcherAction.java b/src/main/java/org/mockito/internal/invocation/ArgumentMatcherAction.java
new file mode 100644
index 0000000..f2b544f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/invocation/ArgumentMatcherAction.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.mockito.ArgumentMatcher;
+
+public interface ArgumentMatcherAction {
+    /**
+     * Implementations must apply the given matcher to the argument and return
+     * <code>true</code> if the operation was successful or <code>false</code>
+     * if not. In this case no more matchers and arguments will be passed by
+     * {@link MatcherApplicationStrategy#forEachMatcherAndArgument(ArgumentMatcherAction)} to this method.
+     * .
+     *
+     * @param matcher
+     *            to process the argument, never <code>null</code>
+     * @param argument
+     *            to be processed by the matcher, can be <code>null</code>
+     * @return
+     *         <ul>
+     *         <li><code>true</code> if the <b>matcher</b> was successfully
+     *         applied to the <b>argument</b> and the next pair of matcher and
+     *         argument should be passed
+     *         <li><code>false</code> otherwise
+     *         </ul>
+     *
+     *
+     */
+    boolean apply(ArgumentMatcher<?> matcher, Object argument);
+}
diff --git a/src/main/java/org/mockito/internal/invocation/ArgumentsComparator.java b/src/main/java/org/mockito/internal/invocation/ArgumentsComparator.java
deleted file mode 100644
index 1f16c92..0000000
--- a/src/main/java/org/mockito/internal/invocation/ArgumentsComparator.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.invocation;

-

-import org.hamcrest.Matcher;

-import org.mockito.internal.matchers.MatcherDecorator;

-import org.mockito.internal.matchers.VarargMatcher;

-import org.mockito.invocation.Invocation;

-

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public class ArgumentsComparator {

-    public boolean argumentsMatch(InvocationMatcher invocationMatcher, Invocation actual) {

-        Object[] actualArgs = actual.getArguments();

-        return argumentsMatch(invocationMatcher, actualArgs) || varArgsMatch(invocationMatcher, actual);

-    }

-

-    public boolean argumentsMatch(InvocationMatcher invocationMatcher, Object[] actualArgs) {

-        if (actualArgs.length != invocationMatcher.getMatchers().size()) {

-            return false;

-        }

-        for (int i = 0; i < actualArgs.length; i++) {

-            if (!invocationMatcher.getMatchers().get(i).matches(actualArgs[i])) {

-                return false;

-            }

-        }

-        return true;

-    }

-

-    //ok, this method is a little bit messy but the vararg business unfortunately is messy...      

-    private boolean varArgsMatch(InvocationMatcher invocationMatcher, Invocation actual) {

-        if (!actual.getMethod().isVarArgs()) {

-            //if the method is not vararg forget about it

-            return false;

-        }

-

-        //we must use raw arguments, not arguments...

-        Object[] rawArgs = actual.getRawArguments();

-        List<Matcher> matchers = invocationMatcher.getMatchers();

-

-        if (rawArgs.length != matchers.size()) {

-            return false;

-        }

-

-        for (int i = 0; i < rawArgs.length; i++) {

-            Matcher m = matchers.get(i);

-            //it's a vararg because it's the last array in the arg list

-            if (rawArgs[i] != null && rawArgs[i].getClass().isArray() && i == rawArgs.length-1) {

-                Matcher actualMatcher;

-                //this is necessary as the framework often decorates matchers

-                if (m instanceof MatcherDecorator) {

-                    actualMatcher = ((MatcherDecorator)m).getActualMatcher();

-                } else {

-                    actualMatcher = m;

-                }

-                //this is very important to only allow VarargMatchers here. If you're not sure why remove it and run all tests.

-                if (!(actualMatcher instanceof VarargMatcher) || !actualMatcher.matches(rawArgs[i])) {

-                    return false;

-                }

-            //it's not a vararg (i.e. some ordinary argument before varargs), just do the ordinary check

-            } else if (!m.matches(rawArgs[i])){

-                return false;

-            }

-        }

-

-        return true;

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/invocation/ArgumentsProcessor.java b/src/main/java/org/mockito/internal/invocation/ArgumentsProcessor.java
index d0a6a5e..b6248d6 100644
--- a/src/main/java/org/mockito/internal/invocation/ArgumentsProcessor.java
+++ b/src/main/java/org/mockito/internal/invocation/ArgumentsProcessor.java
@@ -4,10 +4,9 @@
  */
 package org.mockito.internal.invocation;
 
-import org.hamcrest.Matcher;
+import org.mockito.ArgumentMatcher;
 import org.mockito.internal.matchers.ArrayEquals;
 import org.mockito.internal.matchers.Equals;
-import org.mockito.internal.util.collections.ArrayUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -19,7 +18,7 @@
     // expands array varArgs that are given by runtime (1, [a, b]) into true
     // varArgs (1, a, b);
     public static Object[] expandVarArgs(final boolean isVarArgs, final Object[] args) {
-        if (!isVarArgs || new ArrayUtils().isEmpty(args) || args[args.length - 1] != null && !args[args.length - 1].getClass().isArray()) {
+        if (!isVarArgs || isNullOrEmpty(args) || args[args.length - 1] != null && !args[args.length - 1].getClass().isArray()) {
             return args == null ? new Object[0] : args;
         }
 
@@ -38,8 +37,12 @@
         return newArgs;
     }
 
-    public static List<Matcher> argumentsToMatchers(Object[] arguments) {
-        List<Matcher> matchers = new ArrayList<Matcher>(arguments.length);
+    private static <T> boolean isNullOrEmpty(T[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static List<ArgumentMatcher> argumentsToMatchers(Object[] arguments) {
+        List<ArgumentMatcher> matchers = new ArrayList<ArgumentMatcher>(arguments.length);
         for (Object arg : arguments) {
             if (arg != null && arg.getClass().isArray()) {
                 matchers.add(new ArrayEquals(arg));
@@ -49,4 +52,6 @@
         }
         return matchers;
     }
+
+
 }
diff --git a/src/main/java/org/mockito/internal/invocation/CapturesArgumensFromInvocation.java b/src/main/java/org/mockito/internal/invocation/CapturesArgumensFromInvocation.java
deleted file mode 100644
index 2e32bdd..0000000
--- a/src/main/java/org/mockito/internal/invocation/CapturesArgumensFromInvocation.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.invocation;

-

-

-import org.mockito.invocation.Invocation;

-

-public interface CapturesArgumensFromInvocation {

-    

-    void captureArgumentsFrom(Invocation i);

-    

-}

diff --git a/src/main/java/org/mockito/internal/invocation/InvocationComparator.java b/src/main/java/org/mockito/internal/invocation/InvocationComparator.java
new file mode 100644
index 0000000..46dc08e
--- /dev/null
+++ b/src/main/java/org/mockito/internal/invocation/InvocationComparator.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.mockito.invocation.Invocation;
+
+import java.util.Comparator;
+
+/**
+ * Compares invocations based on the sequence number
+ */
+public class InvocationComparator implements Comparator<Invocation> {
+    public int compare(Invocation o1, Invocation o2) {
+        return Integer.valueOf(o1.getSequenceNumber()).compareTo(o2.getSequenceNumber());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/invocation/InvocationImpl.java b/src/main/java/org/mockito/internal/invocation/InvocationImpl.java
index 19e85f7..a728a0c 100644
--- a/src/main/java/org/mockito/internal/invocation/InvocationImpl.java
+++ b/src/main/java/org/mockito/internal/invocation/InvocationImpl.java
@@ -5,13 +5,13 @@
 
 package org.mockito.internal.invocation;
 
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.debugging.LocationImpl;
 import org.mockito.internal.exceptions.VerificationAwareInvocation;
 import org.mockito.internal.invocation.realmethod.RealMethod;
 import org.mockito.internal.reporting.PrintSettings;
 import org.mockito.invocation.*;
 
+import static org.mockito.internal.exceptions.Reporter.cannotCallAbstractRealMethod;
+
 import java.lang.reflect.Method;
 import java.util.Arrays;
 
@@ -40,14 +40,15 @@
     final RealMethod realMethod;
     private StubInfo stubInfo;
 
-    public InvocationImpl(Object mock, MockitoMethod mockitoMethod, Object[] args, int sequenceNumber, RealMethod realMethod) {
+    public InvocationImpl(Object mock, MockitoMethod mockitoMethod, Object[] args, int sequenceNumber,
+                          RealMethod realMethod, Location location) {
         this.method = mockitoMethod;
         this.mock = mock;
         this.realMethod = realMethod;
         this.arguments = ArgumentsProcessor.expandVarArgs(mockitoMethod.isVarArgs(), args);
         this.rawArguments = args;
         this.sequenceNumber = sequenceNumber;
-        this.location = new LocationImpl();
+        this.location = location;
     }
 
     public Object getMock() {
@@ -63,11 +64,7 @@
     }
 
     public <T> T getArgument(int index) {
-        return (T) arguments[index];
-    }
-
-    public <T> T getArgumentAt(int index, Class<T> clazz) {
-        return (T) arguments[index];
+        return (T)arguments[index];
     }
 
     public boolean isVerified() {
@@ -109,9 +106,13 @@
         return this.rawArguments;
     }
 
+    public Class<?> getRawReturnType() {
+        return method.getReturnType();
+    }
+
     public Object callRealMethod() throws Throwable {
         if (method.isAbstract()) {
-            new Reporter().cannotCallAbstractRealMethod();
+            throw cannotCallAbstractRealMethod();
         }
         return realMethod.invoke(mock, rawArguments);
     }
diff --git a/src/main/java/org/mockito/internal/invocation/InvocationMarker.java b/src/main/java/org/mockito/internal/invocation/InvocationMarker.java
index 4df2e3d..fc48b4d 100644
--- a/src/main/java/org/mockito/internal/invocation/InvocationMarker.java
+++ b/src/main/java/org/mockito/internal/invocation/InvocationMarker.java
@@ -2,31 +2,34 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.invocation;

-

-import java.util.List;

-

-import org.mockito.internal.verification.api.InOrderContext;

-import org.mockito.invocation.Invocation;

-

-public class InvocationMarker {

-

-    public void markVerified(List<Invocation> invocations, CapturesArgumensFromInvocation wanted) {

-        for (Invocation invocation : invocations) {

-            markVerified(invocation, wanted);

-        }

-    }

-

-	public void markVerified(Invocation invocation, CapturesArgumensFromInvocation wanted) {

-		invocation.markVerified();

-		wanted.captureArgumentsFrom(invocation);

-	}

-

-    public void markVerifiedInOrder(List<Invocation> chunk, CapturesArgumensFromInvocation wanted, InOrderContext context) {

-        markVerified(chunk, wanted);

-        

-        for (Invocation i : chunk) {

-            context.markVerified(i);

-        }

-    }

-}
\ No newline at end of file
+package org.mockito.internal.invocation;
+
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+import java.util.List;
+
+public class InvocationMarker {
+
+    private InvocationMarker(){}
+
+    public static void markVerified(List<Invocation> invocations, MatchableInvocation wanted) {
+        for (Invocation invocation : invocations) {
+            markVerified(invocation, wanted);
+        }
+    }
+
+    public static void markVerified(Invocation invocation, MatchableInvocation wanted) {
+        invocation.markVerified();
+        wanted.captureArgumentsFrom(invocation);
+    }
+
+    public static void markVerifiedInOrder(List<Invocation> chunk, MatchableInvocation wanted, InOrderContext context) {
+        markVerified(chunk, wanted);
+
+        for (Invocation i : chunk) {
+            context.markVerified(i);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/invocation/InvocationMatcher.java b/src/main/java/org/mockito/internal/invocation/InvocationMatcher.java
index 98d29b3..83a28ff 100644
--- a/src/main/java/org/mockito/internal/invocation/InvocationMatcher.java
+++ b/src/main/java/org/mockito/internal/invocation/InvocationMatcher.java
@@ -5,160 +5,150 @@
 
 package org.mockito.internal.invocation;
 
-import org.hamcrest.Matcher;
+import static org.mockito.internal.invocation.ArgumentsProcessor.argumentsToMatchers;
+import static org.mockito.internal.invocation.MatcherApplicationStrategy.getMatcherApplicationStrategyFor;
+import static org.mockito.internal.invocation.TypeSafeMatching.matchesTypeSafe;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import org.mockito.ArgumentMatcher;
 import org.mockito.internal.matchers.CapturesArguments;
-import org.mockito.internal.matchers.MatcherDecorator;
-import org.mockito.internal.matchers.VarargMatcher;
 import org.mockito.internal.reporting.PrintSettings;
 import org.mockito.invocation.DescribedInvocation;
 import org.mockito.invocation.Invocation;
 import org.mockito.invocation.Location;
+import org.mockito.invocation.MatchableInvocation;
 
-import java.io.Serializable;
-import java.lang.reflect.Array;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
+/**
+ * In addition to all content of the invocation, the invocation matcher contains the argument matchers. Invocation matcher is used during verification and stubbing. In those cases, the user can provide argument matchers instead of 'raw' arguments. Raw arguments are converted to 'equals' matchers anyway.
+ */
+@SuppressWarnings("serial")
+public class InvocationMatcher implements MatchableInvocation, DescribedInvocation, Serializable {
 
-@SuppressWarnings("unchecked")
-public class InvocationMatcher implements DescribedInvocation, CapturesArgumensFromInvocation, Serializable {
-
-    private static final long serialVersionUID = -3047126096857467610L;
     private final Invocation invocation;
-    private final List<Matcher> matchers;
+    private final List<ArgumentMatcher<?>> matchers;
 
-    public InvocationMatcher(Invocation invocation, List<Matcher> matchers) {
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public InvocationMatcher(Invocation invocation, List<ArgumentMatcher> matchers) {
         this.invocation = invocation;
         if (matchers.isEmpty()) {
-            this.matchers = ArgumentsProcessor.argumentsToMatchers(invocation.getArguments());
+            this.matchers = (List) argumentsToMatchers(invocation.getArguments());
         } else {
-            this.matchers = matchers;
+            this.matchers = (List) matchers;
         }
     }
-    
+
+    @SuppressWarnings("rawtypes")
     public InvocationMatcher(Invocation invocation) {
-        this(invocation, Collections.<Matcher>emptyList());
+        this(invocation, Collections.<ArgumentMatcher> emptyList());
+    }
+
+    public static List<InvocationMatcher> createFrom(List<Invocation> invocations) {
+        LinkedList<InvocationMatcher> out = new LinkedList<InvocationMatcher>();
+        for (Invocation i : invocations) {
+            out.add(new InvocationMatcher(i));
+        }
+        return out;
     }
 
     public Method getMethod() {
         return invocation.getMethod();
     }
-    
+
+    @Override
     public Invocation getInvocation() {
-        return this.invocation;
+        return invocation;
     }
-    
-    public List<Matcher> getMatchers() {
-        return this.matchers;
+
+    @Override
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public List<ArgumentMatcher> getMatchers() {
+        return (List) matchers;
     }
-    
+
+    @Override
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     public String toString() {
-        return new PrintSettings().print(matchers, invocation);
+        return new PrintSettings().print((List) matchers, invocation);
     }
 
-    public boolean matches(Invocation actual) {
-        return invocation.getMock().equals(actual.getMock())
-                && hasSameMethod(actual)
-                && new ArgumentsComparator().argumentsMatch(this, actual);
-    }
-
-    private boolean safelyArgumentsMatch(Object[] actualArgs) {
-        try {
-            return new ArgumentsComparator().argumentsMatch(this, actualArgs);
-        } catch (Throwable t) {
-            return false;
-        }
+    @Override
+    public boolean matches(Invocation candidate) {
+        return invocation.getMock().equals(candidate.getMock()) && hasSameMethod(candidate) && argumentsMatch(candidate);
     }
 
     /**
-     * similar means the same method name, same mock, unverified 
-     * and: if arguments are the same cannot be overloaded
+     * similar means the same method name, same mock, unverified and: if arguments are the same cannot be overloaded
      */
+    @Override
     public boolean hasSimilarMethod(Invocation candidate) {
         String wantedMethodName = getMethod().getName();
-        String currentMethodName = candidate.getMethod().getName();
-        
-        final boolean methodNameEquals = wantedMethodName.equals(currentMethodName);
-        final boolean isUnverified = !candidate.isVerified();
-        final boolean mockIsTheSame = getInvocation().getMock() == candidate.getMock();
-        final boolean methodEquals = hasSameMethod(candidate);
+        String candidateMethodName = candidate.getMethod().getName();
 
-        if (!methodNameEquals || !isUnverified || !mockIsTheSame) {
+        if (!wantedMethodName.equals(candidateMethodName)) {
             return false;
         }
+        if (candidate.isVerified()) {
+            return false;
+        }
+        if (getInvocation().getMock() != candidate.getMock()) {
+            return false;
+        }
+        if (hasSameMethod(candidate)) {
+            return true;
+        }
 
-        final boolean overloadedButSameArgs = !methodEquals && safelyArgumentsMatch(candidate.getArguments());
-
-        return !overloadedButSameArgs;
+        return !argumentsMatch(candidate);
     }
 
+    @Override
     public boolean hasSameMethod(Invocation candidate) {
-        //not using method.equals() for 1 good reason:
-        //sometimes java generates forwarding methods when generics are in play see JavaGenericsForwardingMethodsTest
+        // not using method.equals() for 1 good reason:
+        // sometimes java generates forwarding methods when generics are in play see JavaGenericsForwardingMethodsTest
         Method m1 = invocation.getMethod();
         Method m2 = candidate.getMethod();
-        
+
         if (m1.getName() != null && m1.getName().equals(m2.getName())) {
-        	/* Avoid unnecessary cloning */
-        	Class[] params1 = m1.getParameterTypes();
-        	Class[] params2 = m2.getParameterTypes();
-        	if (params1.length == params2.length) {
-        	    for (int i = 0; i < params1.length; i++) {
-        		if (params1[i] != params2[i])
-        		    return false;
-        	    }
-        	    return true;
-        	}
+            /* Avoid unnecessary cloning */
+            Class<?>[] params1 = m1.getParameterTypes();
+            Class<?>[] params2 = m2.getParameterTypes();
+            return Arrays.equals(params1, params2);
         }
         return false;
     }
-    
+
+    @Override
     public Location getLocation() {
         return invocation.getLocation();
     }
 
+    @Override
     public void captureArgumentsFrom(Invocation invocation) {
-        for (int position = 0; position < matchers.size(); position++) {
-            Matcher m = matchers.get(position);
-            if (m instanceof CapturesArguments && invocation.getRawArguments().length > position) {
-                //TODO SF - this whole lot can be moved captureFrom implementation
-                if(isVariableArgument(invocation, position) && isVarargMatcher(m)) {
-                    Object array = invocation.getRawArguments()[position];
-                    for (int i = 0; i < Array.getLength(array); i++) {
-                        ((CapturesArguments) m).captureFrom(Array.get(array, i));
-                    }
-                    //since we've captured all varargs already, it does not make sense to process other matchers.
-                    return;
-                } else {
-                    ((CapturesArguments) m).captureFrom(invocation.getRawArguments()[position]);
+        MatcherApplicationStrategy strategy = getMatcherApplicationStrategyFor(invocation, matchers);
+        strategy.forEachMatcherAndArgument(captureArgument());
+    }
+
+    private ArgumentMatcherAction captureArgument() {
+        return new ArgumentMatcherAction() {
+
+            @Override
+            public boolean apply(ArgumentMatcher<?> matcher, Object argument) {
+                if (matcher instanceof CapturesArguments) {
+                    ((CapturesArguments) matcher).captureFrom(argument);
                 }
+
+                return true;
             }
-        }
+        };
     }
 
-    private boolean isVarargMatcher(Matcher matcher) {
-        Matcher actualMatcher = matcher;
-        if (actualMatcher instanceof MatcherDecorator) {
-            actualMatcher = ((MatcherDecorator) actualMatcher).getActualMatcher();
-        }
-        return actualMatcher instanceof VarargMatcher;
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private boolean argumentsMatch(Invocation actual) {
+        List matchers = getMatchers();
+        return getMatcherApplicationStrategyFor(actual, matchers).forEachMatcherAndArgument( matchesTypeSafe());
     }
-
-    private boolean isVariableArgument(Invocation invocation, int position) {
-        return invocation.getRawArguments().length - 1 == position
-                && invocation.getRawArguments()[position] != null
-                && invocation.getRawArguments()[position].getClass().isArray()
-                && invocation.getMethod().isVarArgs();
-    }
-
-    public static List<InvocationMatcher> createFrom(List<Invocation> invocations) {
-        LinkedList<InvocationMatcher> out = new LinkedList<InvocationMatcher>();
-
-        for (Invocation i : invocations) {
-            out.add(new InvocationMatcher(i));
-        }
-
-        return out;
-    }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/invocation/InvocationsFinder.java b/src/main/java/org/mockito/internal/invocation/InvocationsFinder.java
index 3e30cb0..57c335f 100644
--- a/src/main/java/org/mockito/internal/invocation/InvocationsFinder.java
+++ b/src/main/java/org/mockito/internal/invocation/InvocationsFinder.java
@@ -13,45 +13,49 @@
 import org.mockito.internal.verification.api.InOrderContext;
 import org.mockito.invocation.Invocation;
 import org.mockito.invocation.Location;
+import org.mockito.invocation.MatchableInvocation;
 
 public class InvocationsFinder {
 
-    public List<Invocation> findInvocations(List<Invocation> invocations, InvocationMatcher wanted) {
+    private InvocationsFinder() {
+    }
+
+    public static List<Invocation> findInvocations(List<Invocation> invocations, MatchableInvocation wanted) {
         return ListUtil.filter(invocations, new RemoveNotMatching(wanted));
     }
 
-    public List<Invocation> findAllMatchingUnverifiedChunks(List<Invocation> invocations, InvocationMatcher wanted, InOrderContext orderingContext) {
+    public static List<Invocation> findAllMatchingUnverifiedChunks(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext orderingContext) {
         List<Invocation> unverified = removeVerifiedInOrder(invocations, orderingContext);
         return ListUtil.filter(unverified, new RemoveNotMatching(wanted));
     }
 
     /**
      * some examples how it works:
-     * 
+     *
      * Given invocations sequence:
      * 1,1,2,1
-     * 
+     *
      * if wanted is 1 and mode is times(2) then returns
-     * 1,1  
-     * 
+     * 1,1
+     *
      * if wanted is 1 and mode is atLeast() then returns
      * 1,1,1
-     * 
+     *
      * if wanted is 1 and mode is times(x), where x != 2 then returns
      * 1,1,1
      */
-    public List<Invocation> findMatchingChunk(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount, InOrderContext context) {
+    public static List<Invocation> findMatchingChunk(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount, InOrderContext context) {
         List<Invocation> unverified = removeVerifiedInOrder(invocations, context);
         List<Invocation> firstChunk = getFirstMatchingChunk(wanted, unverified);
-        
+
         if (wantedCount != firstChunk.size()) {
-            return this.findAllMatchingUnverifiedChunks(invocations, wanted, context);
+            return findAllMatchingUnverifiedChunks(invocations, wanted, context);
         } else {
             return firstChunk;
         }
     }
 
-    private List<Invocation> getFirstMatchingChunk(InvocationMatcher wanted, List<Invocation> unverified) {
+    private static List<Invocation> getFirstMatchingChunk(MatchableInvocation wanted, List<Invocation> unverified) {
         List<Invocation> firstChunk = new LinkedList<Invocation>();
         for (Invocation invocation : unverified) {
             if (wanted.matches(invocation)) {
@@ -62,8 +66,8 @@
         }
         return firstChunk;
     }
-    
-    public Invocation findFirstMatchingUnverifiedInvocation( List<Invocation> invocations, InvocationMatcher wanted, InOrderContext context ){
+
+    public static Invocation findFirstMatchingUnverifiedInvocation(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext context ){
         for( Invocation invocation : removeVerifiedInOrder( invocations, context )){
             if( wanted.matches( invocation )){
                 return invocation;
@@ -71,8 +75,8 @@
         }
         return null;
     }
-    
-    public Invocation findSimilarInvocation(List<Invocation> invocations, InvocationMatcher wanted) {
+
+    public static Invocation findSimilarInvocation(List<Invocation> invocations, MatchableInvocation wanted) {
         Invocation firstSimilar = null;
         for (Invocation invocation : invocations) {
             if (!wanted.hasSimilarMethod(invocation)) {
@@ -85,15 +89,15 @@
                 return invocation;
             }
         }
-        
+
         return firstSimilar;
     }
-    
-    public Invocation findFirstUnverified(List<Invocation> invocations) {
+
+    public static Invocation findFirstUnverified(List<Invocation> invocations) {
         return findFirstUnverified(invocations, null);
     }
-    
-    Invocation findFirstUnverified(List<Invocation> invocations, Object mock) {
+
+    static Invocation findFirstUnverified(List<Invocation> invocations, Object mock) {
         for (Invocation i : invocations) {
             boolean mockIsValid = mock == null || mock == i.getMock();
             if (!i.isVerified() && mockIsValid) {
@@ -103,7 +107,7 @@
         return null;
     }
 
-    public Location getLastLocation(List<Invocation> invocations) {
+    public static Location getLastLocation(List<Invocation> invocations) {
         if (invocations.isEmpty()) {
             return null;
         } else {
@@ -111,18 +115,18 @@
             return last.getLocation();
         }
     }
-    
-    public Invocation findPreviousVerifiedInOrder(List<Invocation> invocations, InOrderContext context) {
+
+    public static Invocation findPreviousVerifiedInOrder(List<Invocation> invocations, InOrderContext context) {
         LinkedList<Invocation> verifiedOnly = ListUtil.filter(invocations, new RemoveUnverifiedInOrder(context));
-        
+
         if (verifiedOnly.isEmpty()) {
             return null;
         } else {
             return verifiedOnly.getLast();
         }
     }
-    
-    private List<Invocation> removeVerifiedInOrder(List<Invocation> invocations, InOrderContext orderingContext) {
+
+    private static List<Invocation> removeVerifiedInOrder(List<Invocation> invocations, InOrderContext orderingContext) {
         List<Invocation> unverified = new LinkedList<Invocation>();
         for (Invocation i : invocations) {
             if (orderingContext.isVerified(i)) {
@@ -133,11 +137,11 @@
         }
         return unverified;
     }
-    
-    private static class RemoveNotMatching implements Filter<Invocation> {
-        private final InvocationMatcher wanted;
 
-        private RemoveNotMatching(InvocationMatcher wanted) {
+    private static class RemoveNotMatching implements Filter<Invocation> {
+        private final MatchableInvocation wanted;
+
+        private RemoveNotMatching(MatchableInvocation wanted) {
             this.wanted = wanted;
         }
 
@@ -160,19 +164,19 @@
 
     /**
      * i3 is unverified here:
-     * 
+     *
      * i1, i2, i3
      *     v
-     *     
+     *
      * all good here:
-     * 
+     *
      * i1, i2, i3
      *     v   v
-     * 
+     *
      * @param context
      * @param orderedInvocations
      */
-    public Invocation findFirstUnverifiedInOrder(InOrderContext context, List<Invocation> orderedInvocations) {
+    public static Invocation findFirstUnverifiedInOrder(InOrderContext context, List<Invocation> orderedInvocations) {
         Invocation candidate = null;
         for(Invocation i : orderedInvocations) {
             if (!context.isVerified(i)) {
@@ -183,4 +187,4 @@
         }
         return candidate;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java b/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java
new file mode 100644
index 0000000..e085c25
--- /dev/null
+++ b/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS;
+import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.MATCH_EACH_VARARGS_WITH_LAST_MATCHER;
+import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.ONE_MATCHER_PER_ARGUMENT;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.CapturingMatcher;
+import org.mockito.internal.matchers.VarargMatcher;
+import org.mockito.invocation.Invocation;
+
+public class MatcherApplicationStrategy {
+
+    private final Invocation invocation;
+    private final List<ArgumentMatcher<?>> matchers;
+    private final MatcherApplicationType matchingType;
+
+
+
+    private MatcherApplicationStrategy(Invocation invocation, List<ArgumentMatcher<?>> matchers, MatcherApplicationType matchingType) {
+        this.invocation = invocation;
+        if (matchingType == MATCH_EACH_VARARGS_WITH_LAST_MATCHER) {
+            int times = varargLength(invocation);
+            this.matchers = appendLastMatcherNTimes(matchers, times);
+        } else {
+            this.matchers = matchers;
+        }
+
+        this.matchingType = matchingType;
+    }
+
+    /**
+     * Returns the {@link MatcherApplicationStrategy} that must be used to capture the
+     * arguments of the given <b>invocation</b> using the given <b>matchers</b>.
+     *
+     * @param invocation
+     *            that contain the arguments to capture
+     * @param matchers
+     *            that will be used to capture the arguments of the invocation,
+     *            the passed {@link List} is not required to contain a
+     *            {@link CapturingMatcher}
+     * @return never <code>null</code>
+     */
+    public static MatcherApplicationStrategy getMatcherApplicationStrategyFor(Invocation invocation, List<ArgumentMatcher<?>> matchers) {
+
+        MatcherApplicationType type = getMatcherApplicationType(invocation, matchers);
+        return new MatcherApplicationStrategy(invocation, matchers, type);
+    }
+
+    /**
+     * Applies the given {@link ArgumentMatcherAction} to all arguments and
+     * corresponding matchers
+     *
+     * @param action
+     *            must not be <code>null</code>
+     * @return
+     *         <ul>
+     *         <li><code>true</code> if the given <b>action</b> returned
+     *         <code>true</code> for all arguments and matchers passed to it.
+     *         <li><code>false</code> if the given <b>action</b> returned
+     *         <code>false</code> for one of the passed arguments and matchers
+     *         <li><code>false</code> if the given matchers don't fit to the given invocation
+     *         because too many or to few matchers are available.
+     *         </ul>
+     */
+    public boolean forEachMatcherAndArgument(ArgumentMatcherAction action) {
+        if (matchingType == ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS)
+            return false;
+
+        Object[] arguments = invocation.getArguments();
+        for (int i = 0; i < arguments.length; i++) {
+            ArgumentMatcher<?> matcher = matchers.get(i);
+            Object argument = arguments[i];
+
+            if (!action.apply(matcher, argument)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static MatcherApplicationType getMatcherApplicationType(Invocation invocation, List<ArgumentMatcher<?>> matchers) {
+        final int rawArguments = invocation.getRawArguments().length;
+        final int expandedArguments = invocation.getArguments().length;
+        final int matcherCount = matchers.size();
+
+        if (expandedArguments == matcherCount) {
+            return ONE_MATCHER_PER_ARGUMENT;
+        }
+
+        if (rawArguments == matcherCount && isLastMatcherVargargMatcher(matchers)) {
+            return MATCH_EACH_VARARGS_WITH_LAST_MATCHER;
+        }
+
+        return ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS;
+    }
+
+    private static boolean isLastMatcherVargargMatcher(final List<ArgumentMatcher<?>> matchers) {
+        return lastMatcher(matchers) instanceof VarargMatcher;
+    }
+
+    private static List<ArgumentMatcher<?>> appendLastMatcherNTimes(List<ArgumentMatcher<?>> matchers, int timesToAppendLastMatcher) {
+        ArgumentMatcher<?> lastMatcher = lastMatcher(matchers);
+
+        List<ArgumentMatcher<?>> expandedMatchers = new ArrayList<ArgumentMatcher<?>>(matchers);
+        for (int i = 0; i < timesToAppendLastMatcher; i++) {
+            expandedMatchers.add(lastMatcher);
+        }
+        return expandedMatchers;
+    }
+
+    private static int varargLength(Invocation invocation) {
+        int rawArgumentCount = invocation.getRawArguments().length;
+        int expandedArgumentCount = invocation.getArguments().length;
+        return expandedArgumentCount - rawArgumentCount;
+    }
+
+    private static ArgumentMatcher<?> lastMatcher(List<ArgumentMatcher<?>> matchers) {
+        return matchers.get(matchers.size() - 1);
+    }
+
+    enum MatcherApplicationType {
+        ONE_MATCHER_PER_ARGUMENT, MATCH_EACH_VARARGS_WITH_LAST_MATCHER, ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/invocation/MatchersBinder.java b/src/main/java/org/mockito/internal/invocation/MatchersBinder.java
index c40d3f7..8a01d2c 100644
--- a/src/main/java/org/mockito/internal/invocation/MatchersBinder.java
+++ b/src/main/java/org/mockito/internal/invocation/MatchersBinder.java
@@ -5,26 +5,30 @@
 
 package org.mockito.internal.invocation;
 
-import org.hamcrest.Matcher;
-import org.mockito.exceptions.Reporter;
+
+import static org.mockito.internal.exceptions.Reporter.invalidUseOfMatchers;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.mockito.ArgumentMatcher;
 import org.mockito.internal.matchers.LocalizedMatcher;
 import org.mockito.internal.progress.ArgumentMatcherStorage;
 import org.mockito.invocation.Invocation;
 
-import java.io.Serializable;
-import java.util.List;
-
 @SuppressWarnings("unchecked")
 public class MatchersBinder implements Serializable {
 
-    private static final long serialVersionUID = -311433939339443463L;
-
     public InvocationMatcher bindMatchers(ArgumentMatcherStorage argumentMatcherStorage, Invocation invocation) {
         List<LocalizedMatcher> lastMatchers = argumentMatcherStorage.pullLocalizedMatchers();
         validateMatchers(invocation, lastMatchers);
 
-        InvocationMatcher invocationWithMatchers = new InvocationMatcher(invocation, (List<Matcher>)(List) lastMatchers);
-        return invocationWithMatchers;
+        List<ArgumentMatcher> matchers = new LinkedList<ArgumentMatcher>();
+        for (LocalizedMatcher m : lastMatchers) {
+            matchers.add(m.getMatcher());
+        }
+        return new InvocationMatcher(invocation, matchers);
     }
 
     private void validateMatchers(Invocation invocation, List<LocalizedMatcher> lastMatchers) {
@@ -32,8 +36,8 @@
             int recordedMatchersSize = lastMatchers.size();
             int expectedMatchersSize = invocation.getArguments().length;
             if (expectedMatchersSize != recordedMatchersSize) {
-                new Reporter().invalidUseOfMatchers(expectedMatchersSize, lastMatchers);
+                throw invalidUseOfMatchers(expectedMatchersSize, lastMatchers);
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/invocation/MockitoMethod.java b/src/main/java/org/mockito/internal/invocation/MockitoMethod.java
index 1048b55..69637c9 100644
--- a/src/main/java/org/mockito/internal/invocation/MockitoMethod.java
+++ b/src/main/java/org/mockito/internal/invocation/MockitoMethod.java
@@ -1,22 +1,22 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.invocation;

-

-import java.lang.reflect.Method;

-

-public interface MockitoMethod extends AbstractAwareMethod {

-

-    public String getName();

-

-    public Class<?> getReturnType();

-

-    public Class<?>[] getParameterTypes();

-

-    public Class<?>[] getExceptionTypes();

-

-    public boolean isVarArgs();

-

-    public Method getJavaMethod();

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import java.lang.reflect.Method;
+
+public interface MockitoMethod extends AbstractAwareMethod {
+
+    String getName();
+
+    Class<?> getReturnType();
+
+    Class<?>[] getParameterTypes();
+
+    Class<?>[] getExceptionTypes();
+
+    boolean isVarArgs();
+
+    Method getJavaMethod();
+}
diff --git a/src/main/java/org/mockito/internal/invocation/SerializableMethod.java b/src/main/java/org/mockito/internal/invocation/SerializableMethod.java
index 2bb534b..5dc8e70 100644
--- a/src/main/java/org/mockito/internal/invocation/SerializableMethod.java
+++ b/src/main/java/org/mockito/internal/invocation/SerializableMethod.java
@@ -1,109 +1,116 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.invocation;

-

-import org.mockito.exceptions.base.MockitoException;

-

-import java.io.Serializable;

-import java.lang.reflect.Method;

-import java.lang.reflect.Modifier;

-import java.util.Arrays;

-

-public class SerializableMethod implements Serializable, MockitoMethod {

-

-    private static final long serialVersionUID = 6005610965006048445L;

-

-    private final Class<?> declaringClass;

-    private final String methodName;

-    private final Class<?>[] parameterTypes;

-    private final Class<?> returnType;

-    private final Class<?>[] exceptionTypes;

-    private final boolean isVarArgs;

-    private final boolean isAbstract;

-

-    public SerializableMethod(Method method) {

-        declaringClass = method.getDeclaringClass();

-        methodName = method.getName();

-        parameterTypes = method.getParameterTypes();

-        returnType = method.getReturnType();

-        exceptionTypes = method.getExceptionTypes();

-        isVarArgs = method.isVarArgs();

-        isAbstract = (method.getModifiers() & Modifier.ABSTRACT) != 0;

-    }

-

-    public String getName() {

-        return methodName;

-    }

-

-    public Class<?> getReturnType() {

-        return returnType;

-    }

-

-    public Class<?>[] getParameterTypes() {

-        return parameterTypes;

-    }

-

-    public Class<?>[] getExceptionTypes() {

-        return exceptionTypes;

-    }

-

-    public boolean isVarArgs() {

-        return isVarArgs;

-    }

-

-    public boolean isAbstract() {

-        return isAbstract;

-    }

-

-    public Method getJavaMethod() {

-        try {

-            return declaringClass.getDeclaredMethod(methodName, parameterTypes);

-        } catch (SecurityException e) {

-            String message = String.format(

-                    "The method %1$s.%2$s is probably private or protected and cannot be mocked.\n" +

-                            "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);

-            throw new MockitoException(message, e);

-        } catch (NoSuchMethodException e) {

-            String message = String.format(

-                    "The method %1$s.%2$s does not exists and you should not get to this point.\n" +

-                            "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);

-            throw new MockitoException(message, e);

-        }

-    }

-

-    @Override

-    public int hashCode() {

-        return 1;

-    }

-

-    @Override

-    public boolean equals(Object obj) {

-        if (this == obj)

-            return true;

-        if (obj == null)

-            return false;

-        if (getClass() != obj.getClass())

-            return false;

-        SerializableMethod other = (SerializableMethod) obj;

-        if (declaringClass == null) {

-            if (other.declaringClass != null)

-                return false;

-        } else if (!declaringClass.equals(other.declaringClass))

-            return false;

-        if (methodName == null) {

-            if (other.methodName != null)

-                return false;

-        } else if (!methodName.equals(other.methodName))

-            return false;

-        if (!Arrays.equals(parameterTypes, other.parameterTypes))

-            return false;

-        if (returnType == null) {

-            if (other.returnType != null)

-                return false;

-        } else if (!returnType.equals(other.returnType))

-            return false;

-        return true;

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.mockito.exceptions.base.MockitoException;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+
+public class SerializableMethod implements Serializable, MockitoMethod {
+
+    private static final long serialVersionUID = 6005610965006048445L;
+
+    private final Class<?> declaringClass;
+    private final String methodName;
+    private final Class<?>[] parameterTypes;
+    private final Class<?> returnType;
+    private final Class<?>[] exceptionTypes;
+    private final boolean isVarArgs;
+    private final boolean isAbstract;
+
+    private volatile transient Method method;
+
+    public SerializableMethod(Method method) {
+        this.method = method;
+        declaringClass = method.getDeclaringClass();
+        methodName = method.getName();
+        parameterTypes = method.getParameterTypes();
+        returnType = method.getReturnType();
+        exceptionTypes = method.getExceptionTypes();
+        isVarArgs = method.isVarArgs();
+        isAbstract = (method.getModifiers() & Modifier.ABSTRACT) != 0;
+    }
+
+    public String getName() {
+        return methodName;
+    }
+
+    public Class<?> getReturnType() {
+        return returnType;
+    }
+
+    public Class<?>[] getParameterTypes() {
+        return parameterTypes;
+    }
+
+    public Class<?>[] getExceptionTypes() {
+        return exceptionTypes;
+    }
+
+    public boolean isVarArgs() {
+        return isVarArgs;
+    }
+
+    public boolean isAbstract() {
+        return isAbstract;
+    }
+
+    public Method getJavaMethod() {
+        if (method != null) {
+            return method;
+        }
+        try {
+            method = declaringClass.getDeclaredMethod(methodName, parameterTypes);
+            return method;
+        } catch (SecurityException e) {
+            String message = String.format(
+                    "The method %1$s.%2$s is probably private or protected and cannot be mocked.\n" +
+                            "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);
+            throw new MockitoException(message, e);
+        } catch (NoSuchMethodException e) {
+            String message = String.format(
+                    "The method %1$s.%2$s does not exists and you should not get to this point.\n" +
+                            "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);
+            throw new MockitoException(message, e);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return 1;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SerializableMethod other = (SerializableMethod) obj;
+        if (declaringClass == null) {
+            if (other.declaringClass != null)
+                return false;
+        } else if (!declaringClass.equals(other.declaringClass))
+            return false;
+        if (methodName == null) {
+            if (other.methodName != null)
+                return false;
+        } else if (!methodName.equals(other.methodName))
+            return false;
+        if (!Arrays.equals(parameterTypes, other.parameterTypes))
+            return false;
+        if (returnType == null) {
+            if (other.returnType != null)
+                return false;
+        } else if (!returnType.equals(other.returnType))
+            return false;
+        return true;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/invocation/StubInfoImpl.java b/src/main/java/org/mockito/internal/invocation/StubInfoImpl.java
index 9e63afe..794d25a 100644
--- a/src/main/java/org/mockito/internal/invocation/StubInfoImpl.java
+++ b/src/main/java/org/mockito/internal/invocation/StubInfoImpl.java
@@ -1,24 +1,24 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.invocation;

-

-import org.mockito.invocation.DescribedInvocation;

-import org.mockito.invocation.Location;

-import org.mockito.invocation.StubInfo;

-

-import java.io.Serializable;

-

-public class StubInfoImpl implements StubInfo, Serializable {

-    private static final long serialVersionUID = 2125827349332068867L;

-    private final DescribedInvocation stubbedAt;

-

-    public StubInfoImpl(DescribedInvocation stubbedAt) {

-        this.stubbedAt = stubbedAt;

-    }

-

-    public Location stubbedAt() {

-        return stubbedAt.getLocation();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Location;
+import org.mockito.invocation.StubInfo;
+
+import java.io.Serializable;
+
+public class StubInfoImpl implements StubInfo, Serializable {
+    private static final long serialVersionUID = 2125827349332068867L;
+    private final DescribedInvocation stubbedAt;
+
+    public StubInfoImpl(DescribedInvocation stubbedAt) {
+        this.stubbedAt = stubbedAt;
+    }
+
+    public Location stubbedAt() {
+        return stubbedAt.getLocation();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/invocation/TypeSafeMatching.java b/src/main/java/org/mockito/internal/invocation/TypeSafeMatching.java
new file mode 100644
index 0000000..2c68435
--- /dev/null
+++ b/src/main/java/org/mockito/internal/invocation/TypeSafeMatching.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import java.lang.reflect.Method;
+
+import org.mockito.ArgumentMatcher;
+
+@SuppressWarnings({"unchecked","rawtypes"})
+public class TypeSafeMatching implements ArgumentMatcherAction {
+
+    private final static ArgumentMatcherAction TYPE_SAFE_MATCHING_ACTION = new TypeSafeMatching();
+
+    private TypeSafeMatching() {}
+
+
+    public static ArgumentMatcherAction matchesTypeSafe(){
+        return TYPE_SAFE_MATCHING_ACTION;
+    }
+    @Override
+    public boolean apply(ArgumentMatcher matcher, Object argument) {
+        return isCompatible(matcher, argument) && matcher.matches(argument);
+    }
+
+
+    /**
+     * Returns <code>true</code> if the given <b>argument</b> can be passed to
+     * the given <code>argumentMatcher</code> without causing a
+     * {@link ClassCastException}.
+     */
+    private static boolean isCompatible(ArgumentMatcher<?> argumentMatcher, Object argument) {
+        if (argument == null)
+            return true;
+
+        Class<?> expectedArgumentType = getArgumentType(argumentMatcher);
+
+        return expectedArgumentType.isInstance(argument);
+    }
+
+    /**
+     * Returns the type of {@link ArgumentMatcher#matches(Object)} of the given
+     * {@link ArgumentMatcher} implementation.
+     */
+    private static Class<?> getArgumentType(ArgumentMatcher<?> argumentMatcher) {
+        Method[] methods = argumentMatcher.getClass().getMethods();
+
+        for (Method method : methods) {
+            if (isMatchesMethod(method)) {
+                return method.getParameterTypes()[0];
+            }
+        }
+        throw new NoSuchMethodError("Method 'matches(T)' not found in ArgumentMatcher: " + argumentMatcher + " !\r\n Please file a bug with this stack trace at: https://github.com/mockito/mockito/issues/new ");
+    }
+
+    /**
+     * Returns <code>true</code> if the given method is
+     * {@link ArgumentMatcher#matches(Object)}
+     */
+    private static boolean isMatchesMethod(Method method) {
+        if (method.getParameterTypes().length != 1) {
+            return false;
+        }
+        if (method.isBridge()) {
+            return false;
+        }
+        return method.getName().equals("matches");
+    }
+}
diff --git a/src/main/java/org/mockito/internal/invocation/UnusedStubsFinder.java b/src/main/java/org/mockito/internal/invocation/UnusedStubsFinder.java
index 451dcfb..b37c755 100644
--- a/src/main/java/org/mockito/internal/invocation/UnusedStubsFinder.java
+++ b/src/main/java/org/mockito/internal/invocation/UnusedStubsFinder.java
@@ -12,17 +12,18 @@
 
 import java.util.*;
 
+@Deprecated
 public class UnusedStubsFinder {
 
     /**
      * Finds all unused stubs for given mocks
-     * 
-     * @param mocks
+     *
+     * @param mocks full list of mocks
      */
     public List<Invocation> find(List<?> mocks) {
         List<Invocation> unused = new LinkedList<Invocation>();
         for (Object mock : mocks) {
-            InternalMockHandler<Object> handler = new MockUtil().getMockHandler(mock);
+            InternalMockHandler<Object> handler = MockUtil.getMockHandler(mock);
             List<StubbedInvocationMatcher> fromSingleMock = handler.getInvocationContainer().getStubbedInvocations();
             for(StubbedInvocationMatcher s : fromSingleMock) {
                 if (!s.wasUsed()) {
@@ -32,4 +33,4 @@
         }
         return unused;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/invocation/finder/AllInvocationsFinder.java b/src/main/java/org/mockito/internal/invocation/finder/AllInvocationsFinder.java
index cfe3346..15dafdf 100644
--- a/src/main/java/org/mockito/internal/invocation/finder/AllInvocationsFinder.java
+++ b/src/main/java/org/mockito/internal/invocation/finder/AllInvocationsFinder.java
@@ -5,34 +5,47 @@
 
 package org.mockito.internal.invocation.finder;
 
-import org.mockito.internal.InternalMockHandler;
-import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.invocation.InvocationComparator;
+import org.mockito.stubbing.Stubbing;
+import org.mockito.internal.stubbing.StubbingComparator;
+import org.mockito.internal.util.DefaultMockingDetails;
 import org.mockito.invocation.Invocation;
 
 import java.util.*;
 
 public class AllInvocationsFinder {
-    
+
+    private AllInvocationsFinder() {}
+
     /**
-     * gets all invocations from mocks. Invocations are ordered earlier first. 
-     * 
+     * gets all invocations from mocks. Invocations are ordered earlier first.
+     *
      * @param mocks mocks
      * @return invocations
      */
-    public List<Invocation> find(List<?> mocks) {
-        Set<Invocation> invocationsInOrder = new TreeSet<Invocation>(new SequenceNumberComparator());
+    public static List<Invocation> find(Iterable<?> mocks) {
+        Set<Invocation> invocationsInOrder = new TreeSet<Invocation>(new InvocationComparator());
         for (Object mock : mocks) {
-            InternalMockHandler<Object> handler = new MockUtil().getMockHandler(mock);
-            List<Invocation> fromSingleMock = handler.getInvocationContainer().getInvocations();
+            Collection<Invocation> fromSingleMock = new DefaultMockingDetails(mock).getInvocations();
             invocationsInOrder.addAll(fromSingleMock);
         }
-        
+
         return new LinkedList<Invocation>(invocationsInOrder);
     }
 
-    private static final class SequenceNumberComparator implements Comparator<Invocation> {
-        public int compare(Invocation o1, Invocation o2) {
-            return Integer.valueOf(o1.getSequenceNumber()).compareTo(o2.getSequenceNumber());
+    /**
+     * Gets all stubbings from mocks. Invocations are ordered earlier first.
+     *
+     * @param mocks mocks
+     * @return stubbings
+     */
+    public static Set<Stubbing> findStubbings(Iterable<?> mocks) {
+        Set<Stubbing> stubbings = new TreeSet<Stubbing>(new StubbingComparator());
+        for (Object mock : mocks) {
+            Collection<? extends Stubbing> fromSingleMock = new DefaultMockingDetails(mock).getStubbings();
+            stubbings.addAll(fromSingleMock);
         }
+
+        return stubbings;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java b/src/main/java/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java
index 2d4a71e..819c7e0 100644
--- a/src/main/java/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java
+++ b/src/main/java/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java
@@ -16,8 +16,10 @@
  */
 public class VerifiableInvocationsFinder {
 
-    public List<Invocation> find(List<?> mocks) {
-        List<Invocation> invocations = new AllInvocationsFinder().find(mocks);
+    private VerifiableInvocationsFinder() {}
+
+    public static List<Invocation> find(List<?> mocks) {
+        List<Invocation> invocations = AllInvocationsFinder.find(mocks);
         return ListUtil.filter(invocations, new RemoveIgnoredForVerification());
     }
 
diff --git a/src/main/java/org/mockito/internal/invocation/package-info.java b/src/main/java/org/mockito/internal/invocation/package-info.java
new file mode 100644
index 0000000..7557fed
--- /dev/null
+++ b/src/main/java/org/mockito/internal/invocation/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Invocation machinery and related classes.
+ */
+package org.mockito.internal.invocation;
diff --git a/src/main/java/org/mockito/internal/invocation/package.html b/src/main/java/org/mockito/internal/invocation/package.html
deleted file mode 100644
index 4ed1db4..0000000
--- a/src/main/java/org/mockito/internal/invocation/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Invocation and related classes. 
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/invocation/realmethod/CleanTraceRealMethod.java b/src/main/java/org/mockito/internal/invocation/realmethod/CleanTraceRealMethod.java
index b7964e8..b55195e 100644
--- a/src/main/java/org/mockito/internal/invocation/realmethod/CleanTraceRealMethod.java
+++ b/src/main/java/org/mockito/internal/invocation/realmethod/CleanTraceRealMethod.java
@@ -33,4 +33,4 @@
             throw t;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/invocation/realmethod/RealMethod.java b/src/main/java/org/mockito/internal/invocation/realmethod/RealMethod.java
index 3f2e785..60ebc87 100644
--- a/src/main/java/org/mockito/internal/invocation/realmethod/RealMethod.java
+++ b/src/main/java/org/mockito/internal/invocation/realmethod/RealMethod.java
@@ -1,11 +1,11 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.invocation.realmethod;

-

-public interface RealMethod {

-

-    Object invoke(Object target, Object[] arguments) throws Throwable;

-

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation.realmethod;
+
+public interface RealMethod {
+
+    Object invoke(Object target, Object[] arguments) throws Throwable;
+
+}
diff --git a/src/main/java/org/mockito/internal/invocation/realmethod/package-info.java b/src/main/java/org/mockito/internal/invocation/realmethod/package-info.java
new file mode 100644
index 0000000..c5204b9
--- /dev/null
+++ b/src/main/java/org/mockito/internal/invocation/realmethod/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Implementations of real method calls.
+ */
+package org.mockito.internal.invocation.realmethod;
diff --git a/src/main/java/org/mockito/internal/invocation/realmethod/package.html b/src/main/java/org/mockito/internal/invocation/realmethod/package.html
deleted file mode 100644
index d89c54f..0000000
--- a/src/main/java/org/mockito/internal/invocation/realmethod/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-implementations of real method calls
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/junit/ArgMismatchFinder.java b/src/main/java/org/mockito/internal/junit/ArgMismatchFinder.java
new file mode 100644
index 0000000..bbd354e
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/ArgMismatchFinder.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import org.mockito.internal.invocation.finder.AllInvocationsFinder;
+import org.mockito.invocation.Invocation;
+import org.mockito.stubbing.Stubbing;
+
+/**
+ * For given mocks, finds stubbing arg mismatches
+ */
+class ArgMismatchFinder {
+
+    StubbingArgMismatches getStubbingArgMismatches(Iterable<Object> mocks) {
+        StubbingArgMismatches mismatches = new StubbingArgMismatches();
+        for (Invocation i : AllInvocationsFinder.find(mocks)) {
+            if (i.stubInfo() != null) {
+                continue;
+            }
+            for (Stubbing stubbing : AllInvocationsFinder.findStubbings(mocks)) {
+                //method name & mock matches
+                if (!stubbing.wasUsed() && stubbing.getInvocation().getMock() == i.getMock()
+                        && stubbing.getInvocation().getMethod().getName().equals(i.getMethod().getName())) {
+                    mismatches.add(i, stubbing.getInvocation());
+                }
+            }
+        }
+        return mismatches;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java b/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java
new file mode 100644
index 0000000..f107c8e
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java
@@ -0,0 +1,73 @@
+package org.mockito.internal.junit;
+
+import org.mockito.internal.exceptions.Reporter;
+import org.mockito.internal.listeners.StubbingLookupListener;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Stubbing;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.mockito.Mockito.mockingDetails;
+
+/**
+ * Default implementation of stubbing lookup listener.
+ * Fails early if stub called with unexpected arguments, but only if current strictness is set to STRICT_STUBS.
+ */
+class DefaultStubbingLookupListener implements StubbingLookupListener {
+
+    private Strictness currentStrictness;
+    private boolean mismatchesReported;
+
+    DefaultStubbingLookupListener(Strictness strictness) {
+        this.currentStrictness = strictness;
+    }
+
+    public void onStubbingLookup(Invocation invocation, MatchableInvocation stubbingFound) {
+        if (currentStrictness != Strictness.STRICT_STUBS) {
+            return;
+        }
+
+        if (stubbingFound == null) {
+            //If stubbing was not found for invocation it means that either the mock invocation was not stubbed or
+            //we have a stubbing arg mismatch.
+            List<Invocation> argMismatchStubbings = potentialArgMismatches(invocation);
+            if (!argMismatchStubbings.isEmpty()) {
+                mismatchesReported = true;
+                Reporter.potentialStubbingProblem(invocation, argMismatchStubbings);
+            }
+        } else {
+            //when strict stubs are in use, every time a stub is realized in the code it is implicitly marked as verified
+            //this way, the users don't have to repeat themselves to verify stubbed invocations (DRY)
+            invocation.markVerified();
+        }
+    }
+
+    private static List<Invocation> potentialArgMismatches(Invocation invocation) {
+        List<Invocation> matchingStubbings = new LinkedList<Invocation>();
+        Collection<Stubbing> stubbings = mockingDetails(invocation.getMock()).getStubbings();
+        for (Stubbing s : stubbings) {
+            if (!s.wasUsed() && s.getInvocation().getMethod().getName().equals(invocation.getMethod().getName())) {
+                matchingStubbings.add(s.getInvocation());
+            }
+        }
+        return matchingStubbings;
+    }
+
+    /**
+     * Enables resetting the strictness to desired level
+     */
+    void setCurrentStrictness(Strictness currentStrictness) {
+        this.currentStrictness = currentStrictness;
+    }
+
+    /**
+     * Indicates that stubbing argument mismatch was reported
+     */
+    boolean isMismatchesReported() {
+        return mismatchesReported;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/DefaultTestFinishedEvent.java b/src/main/java/org/mockito/internal/junit/DefaultTestFinishedEvent.java
new file mode 100644
index 0000000..f18ff83
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/DefaultTestFinishedEvent.java
@@ -0,0 +1,25 @@
+package org.mockito.internal.junit;
+
+public class DefaultTestFinishedEvent implements TestFinishedEvent {
+    private final Object testClassInstance;
+    private final String testMethodName;
+    private final Throwable testFailure;
+
+    public DefaultTestFinishedEvent(Object testClassInstance, String testMethodName, Throwable testFailure) {
+        this.testClassInstance = testClassInstance;
+        this.testMethodName = testMethodName;
+        this.testFailure = testFailure;
+    }
+
+    public Throwable getFailure() {
+        return testFailure;
+    }
+
+    public Object getTestClassInstance() {
+        return testClassInstance;
+    }
+
+    public String getTestMethodName() {
+        return testMethodName;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/ExceptionFactory.java b/src/main/java/org/mockito/internal/junit/ExceptionFactory.java
new file mode 100644
index 0000000..3664aea
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/ExceptionFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import junit.framework.ComparisonFailure;
+import org.mockito.exceptions.verification.ArgumentsAreDifferent;
+
+public class ExceptionFactory {
+
+    private final static boolean hasJUnit = canLoadJunitClass();
+
+    private ExceptionFactory() {
+    }
+
+    /**
+     * If JUnit is used, an AssertionError is returned that extends from JUnit {@link ComparisonFailure} and hence provide a better IDE support as the comparison result is comparable
+     */
+    public static AssertionError createArgumentsAreDifferentException(String message, String wanted, String actual) {
+        if (hasJUnit) {
+            return createJUnitArgumentsAreDifferent(message, wanted, actual);
+        }
+        return new ArgumentsAreDifferent(message);
+    }
+
+    private static AssertionError createJUnitArgumentsAreDifferent(String message, String wanted, String actual) {
+        return JUnitArgsAreDifferent.create(message, wanted, actual);
+    }
+
+    private static boolean canLoadJunitClass() {
+        try {
+            JUnitArgsAreDifferent.create("message", "wanted", "actual");
+        } catch (NoClassDefFoundError onlyIfJUnitIsNotAvailable) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Don't inline this class! It allows create the JUnit-ArgumentsAreDifferent exception without the need to use reflection.
+     * <p>
+     * If JUnit is not available a call to {@link #create(String, String, String)} will throw a {@link NoClassDefFoundError}.
+     * The {@link NoClassDefFoundError} will be thrown by the class loader cause the JUnit class {@link ComparisonFailure}
+     * can't be loaded which is a upper class of ArgumentsAreDifferent.
+     */
+    private static class JUnitArgsAreDifferent {
+        static AssertionError create(String message, String wanted, String actual) {
+            return new org.mockito.exceptions.verification.junit.ArgumentsAreDifferent(message, wanted, actual);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/FriendlyExceptionMaker.java b/src/main/java/org/mockito/internal/junit/FriendlyExceptionMaker.java
deleted file mode 100644
index f454fd2..0000000
--- a/src/main/java/org/mockito/internal/junit/FriendlyExceptionMaker.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.mockito.internal.junit;
-
-import org.mockito.exceptions.verification.ArgumentsAreDifferent;
-
-/**
- * If JUnit is used, we can use an exception that extends from ComparisonFailure
- * and hence provide a better IDE support as the comparison result is comparable
- */
-class FriendlyExceptionMaker {
-
-    private final JUnitDetecter detecter;
-
-    FriendlyExceptionMaker(JUnitDetecter detecter) {
-        this.detecter = detecter;
-    }
-
-    //TODO SF this can be now unit tested
-    public AssertionError createArgumentsAreDifferentException(String message, String wanted, String actual)  {
-        if (!detecter.hasJUnit()) {
-            return new ArgumentsAreDifferent(message);
-        }
-
-        try {
-            Class<?> clazz = Class.forName("org.mockito.exceptions.verification.junit.ArgumentsAreDifferent");
-            AssertionError throwable = (AssertionError) clazz.getConstructors()[0].newInstance(message, wanted, actual);
-            return throwable;
-        } catch (Throwable t) {
-//            throw the default exception in case of problems
-            return new ArgumentsAreDifferent(message);
-        }
-    }
-}
diff --git a/src/main/java/org/mockito/internal/junit/JUnitDetecter.java b/src/main/java/org/mockito/internal/junit/JUnitDetecter.java
deleted file mode 100644
index 3ccc7f0..0000000
--- a/src/main/java/org/mockito/internal/junit/JUnitDetecter.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.mockito.internal.junit;
-
-class JUnitDetecter {
-
-    private boolean hasJUnit;
-
-    JUnitDetecter() {
-        try {
-            Class.forName("junit.framework.ComparisonFailure");
-            hasJUnit = true;
-        } catch (Throwable t) {
-            hasJUnit = false;
-        }
-    }
-
-    public boolean hasJUnit() {
-        return hasJUnit;
-    }
-}
diff --git a/src/main/java/org/mockito/internal/junit/JUnitRule.java b/src/main/java/org/mockito/internal/junit/JUnitRule.java
index a5c0238..8763354 100644
--- a/src/main/java/org/mockito/internal/junit/JUnitRule.java
+++ b/src/main/java/org/mockito/internal/junit/JUnitRule.java
@@ -1,21 +1,80 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.junit;
 
+import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.Statement;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.mockito.quality.Strictness;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.junit.MockitoRule;
 
 /**
  * Internal implementation.
  */
-public class JUnitRule {
-    public Statement apply(final Statement base, final Object target) {
+public class JUnitRule implements MockitoRule {
+
+    private final MockitoLogger logger;
+    private final UniversalTestListener listener;
+
+    /**
+     * @param logger target for the stubbing warnings
+     * @param strictness how strict mocking / stubbing is concerned
+     */
+    public JUnitRule(MockitoLogger logger, Strictness strictness) {
+        this.logger = logger;
+        this.listener = new UniversalTestListener(strictness, logger);
+    }
+
+	@Override
+	public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
         return new Statement() {
-            @Override
             public void evaluate() throws Throwable {
-                MockitoAnnotations.initMocks(target);
-                base.evaluate();
+                //Ideally, JUnit rule should use MockitoSession API so that it dogfoods our public API.
+                //See https://github.com/mockito/mockito/issues/898
+                Mockito.framework().addListener(listener);
+                Throwable testFailure;
+                try {
+                    //mock initialization could be part of listeners but to avoid duplication I left it here:
+                    MockitoAnnotations.initMocks(target);
+                    testFailure = evaluateSafely(base);
+                } finally {
+                    Mockito.framework().removeListener(listener);
+                }
+
+                //If the 'testFinished' fails below, we don't see the original failure, thrown later
+                DefaultTestFinishedEvent event = new DefaultTestFinishedEvent(target, method.getName(), testFailure);
+                listener.testFinished(event);
+
+                if (testFailure != null) {
+                    throw testFailure;
+                }
+
+                //Validate only when there is no test failure to avoid reporting multiple problems
+                //This could be part of the listener but to avoid duplication I left it here:
                 Mockito.validateMockitoUsage();
             }
+
+            private Throwable evaluateSafely(Statement base) {
+                try {
+                    base.evaluate();
+                    return null;
+                } catch (Throwable throwable) {
+                    return throwable;
+                }
+            }
         };
     }
+
+    public MockitoRule silent() {
+        return new JUnitRule(logger, Strictness.LENIENT);
+    }
+
+    public MockitoRule strictness(Strictness strictness) {
+        this.listener.setStrictness(strictness);
+        return this;
+    }
 }
diff --git a/src/main/java/org/mockito/internal/junit/JUnitTool.java b/src/main/java/org/mockito/internal/junit/JUnitTool.java
deleted file mode 100644
index 0d72f96..0000000
--- a/src/main/java/org/mockito/internal/junit/JUnitTool.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.junit;

-

-public class JUnitTool {

-

-    private static JUnitDetecter detecter = new JUnitDetecter();

-

-    public static boolean hasJUnit() {

-        return detecter.hasJUnit();

-    }

-

-    public static AssertionError createArgumentsAreDifferentException(String message, String wanted, String actual)  {

-        return new FriendlyExceptionMaker(detecter).createArgumentsAreDifferentException(message, wanted, actual);

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/junit/MismatchReportingTestListener.java b/src/main/java/org/mockito/internal/junit/MismatchReportingTestListener.java
new file mode 100644
index 0000000..db1f1e9
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/MismatchReportingTestListener.java
@@ -0,0 +1,39 @@
+package org.mockito.internal.junit;
+
+import org.mockito.internal.junit.util.TestName;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.mock.MockCreationSettings;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Reports stubbing argument mismatches to the supplied logger
+ */
+public class MismatchReportingTestListener implements MockitoTestListener {
+
+    private final MockitoLogger logger;
+    private List<Object> mocks = new LinkedList<Object>();
+
+    public MismatchReportingTestListener(MockitoLogger logger) {
+        this.logger = logger;
+    }
+
+    public void testFinished(TestFinishedEvent event) {
+        Collection<Object> createdMocks = mocks;
+        //At this point, we don't need the mocks any more and we can mark all collected mocks for gc
+        //TODO make it better, it's easy to forget to clean up mocks and we still create new instance of list that nobody will read, it's also duplicated
+        mocks = new LinkedList<Object>();
+
+        String testName = TestName.getTestName(event);
+        if (event.getFailure() != null) {
+            //print unused stubbings only when test succeeds to avoid reporting multiple problems and confusing users
+            new ArgMismatchFinder().getStubbingArgMismatches(createdMocks).format(testName, logger);
+        }
+    }
+
+    public void onMockCreated(Object mock, MockCreationSettings settings) {
+        this.mocks.add(mock);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/MockitoTestListener.java b/src/main/java/org/mockito/internal/junit/MockitoTestListener.java
new file mode 100644
index 0000000..8c5f24a
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/MockitoTestListener.java
@@ -0,0 +1,12 @@
+package org.mockito.internal.junit;
+
+import org.mockito.listeners.MockCreationListener;
+
+/**
+ * Internal test listener that helps decoupling JUnit internals from Mockito "business" logic.
+ * If we ever want to expose this type publicly, it should not extend MockCreationListener
+ * because we want our listeners to be single-method interfaces for easier use and evolution.
+ */
+public interface MockitoTestListener extends MockCreationListener {
+    void testFinished(TestFinishedEvent event);
+}
diff --git a/src/main/java/org/mockito/internal/junit/NoOpTestListener.java b/src/main/java/org/mockito/internal/junit/NoOpTestListener.java
new file mode 100644
index 0000000..aa1a40c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/NoOpTestListener.java
@@ -0,0 +1,10 @@
+package org.mockito.internal.junit;
+
+import org.mockito.mock.MockCreationSettings;
+
+public class NoOpTestListener implements MockitoTestListener {
+
+    public void testFinished(TestFinishedEvent event) {}
+
+    public void onMockCreated(Object mock, MockCreationSettings settings) {}
+}
diff --git a/src/main/java/org/mockito/internal/junit/StrictStubsRunnerTestListener.java b/src/main/java/org/mockito/internal/junit/StrictStubsRunnerTestListener.java
new file mode 100644
index 0000000..c32fb0f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/StrictStubsRunnerTestListener.java
@@ -0,0 +1,25 @@
+package org.mockito.internal.junit;
+
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.quality.Strictness;
+
+/**
+ * Fails early when mismatched arguments used for stubbing
+ */
+public class StrictStubsRunnerTestListener implements MockitoTestListener {
+
+    private final DefaultStubbingLookupListener stubbingLookupListener = new DefaultStubbingLookupListener(Strictness.STRICT_STUBS);
+
+    @Override
+    public void testFinished(TestFinishedEvent event) {}
+
+    @Override
+    public void onMockCreated(Object mock, MockCreationSettings settings) {
+        //It is not ideal that we modify the state of MockCreationSettings object
+        //MockCreationSettings is intended to be an immutable view of the creation settings
+        //In future, we should start passing MockSettings object to the creation listener
+        //TODO #793 - when completed, we should be able to get rid of the CreationSettings casting below
+        ((CreationSettings) settings).getStubbingLookupListeners().add(stubbingLookupListener);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/StubbingArgMismatches.java b/src/main/java/org/mockito/internal/junit/StubbingArgMismatches.java
new file mode 100644
index 0000000..3d6342c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/StubbingArgMismatches.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.invocation.Invocation;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Contains stubbing arg mismatches, knows how to format them
+ */
+class StubbingArgMismatches {
+
+    final Map<Invocation, Set<Invocation>> mismatches = new LinkedHashMap<Invocation, Set<Invocation>>();
+
+    public void add(Invocation invocation, Invocation stubbing) {
+        Set<Invocation> matchingInvocations = mismatches.get(stubbing);
+        if (matchingInvocations == null) {
+            matchingInvocations = new LinkedHashSet<Invocation>();
+            mismatches.put(stubbing, matchingInvocations);
+        }
+        matchingInvocations.add(invocation);
+    }
+
+    public void format(String testName, MockitoLogger logger) {
+        if (mismatches.isEmpty()) {
+            return;
+        }
+
+        StubbingHint hint = new StubbingHint(testName);
+        int x = 1;
+        for (Map.Entry<Invocation, Set<Invocation>> m : mismatches.entrySet()) {
+            hint.appendLine(x++, ". Unused... ", m.getKey().getLocation());
+            for (Invocation invocation : m.getValue()) {
+                hint.appendLine(" ...args ok? ", invocation.getLocation());
+            }
+        }
+
+        logger.log(hint.toString());
+    }
+
+    public int size() {
+        return mismatches.size();
+    }
+
+    public String toString() {
+        return "" + mismatches;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/StubbingHint.java b/src/main/java/org/mockito/internal/junit/StubbingHint.java
new file mode 100644
index 0000000..3675a4d
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/StubbingHint.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+/**
+ * Stubbing hint emitted to the user
+ */
+class StubbingHint {
+
+    private final StringBuilder hint;
+
+    StubbingHint(String testName) {
+        hint = new StringBuilder("[MockitoHint] ")
+            .append(testName).append(" (see javadoc for MockitoHint):");
+    }
+
+    void appendLine(Object ... elements) {
+        hint.append("\n[MockitoHint] ");
+        for (Object e : elements) {
+            hint.append(e);
+        }
+    }
+
+    public String toString() {
+        return hint.toString() + "\n";
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/TestFinishedEvent.java b/src/main/java/org/mockito/internal/junit/TestFinishedEvent.java
new file mode 100644
index 0000000..c1bdf1d
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/TestFinishedEvent.java
@@ -0,0 +1,11 @@
+package org.mockito.internal.junit;
+
+public interface TestFinishedEvent {
+
+    Throwable getFailure();
+
+    Object getTestClassInstance();
+
+    String getTestMethodName();
+
+}
diff --git a/src/main/java/org/mockito/internal/junit/UniversalTestListener.java b/src/main/java/org/mockito/internal/junit/UniversalTestListener.java
new file mode 100644
index 0000000..d1500a5
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/UniversalTestListener.java
@@ -0,0 +1,85 @@
+package org.mockito.internal.junit;
+
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.quality.Strictness;
+
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+/**
+ * Universal test listener that behaves accordingly to current setting of strictness.
+ * Will come handy when we offer tweaking strictness at the method level with annotation.
+ * Should be relatively easy to improve and offer tweaking strictness per mock.
+ */
+public class UniversalTestListener implements MockitoTestListener {
+
+    private Strictness currentStrictness;
+    private final MockitoLogger logger;
+
+    private Map<Object, MockCreationSettings> mocks = new IdentityHashMap<Object, MockCreationSettings>();
+    private DefaultStubbingLookupListener stubbingLookupListener;
+
+    public UniversalTestListener(Strictness initialStrictness, MockitoLogger logger) {
+        this.currentStrictness = initialStrictness;
+        this.logger = logger;
+
+        //creating single stubbing lookup listener per junit rule instance / test method
+        //this way, when strictness is updated in the middle of the test it will affect the behavior of the stubbing listener
+        this.stubbingLookupListener = new DefaultStubbingLookupListener(currentStrictness);
+    }
+
+    @Override
+    public void testFinished(TestFinishedEvent event) {
+        Collection<Object> createdMocks = mocks.keySet();
+        //At this point, we don't need the mocks any more and we can mark all collected mocks for gc
+        //TODO make it better, it's easy to forget to clean up mocks and we still create new instance of list that nobody will read, it's also duplicated
+        //TODO clean up all other state, null out stubbingLookupListener
+        mocks = new IdentityHashMap<Object, MockCreationSettings>();
+
+        switch (currentStrictness) {
+            case WARN: emitWarnings(logger, event, createdMocks); break;
+            case STRICT_STUBS: reportUnusedStubs(event, createdMocks); break;
+            case LENIENT: break;
+            default: throw new IllegalStateException("Unknown strictness: " + currentStrictness);
+        }
+    }
+
+    private void reportUnusedStubs(TestFinishedEvent event, Collection<Object> mocks) {
+        //If there is some other failure (or mismatches were detected) don't report another exception to avoid confusion
+        if (event.getFailure() == null && !stubbingLookupListener.isMismatchesReported()) {
+            UnusedStubbings unused = new UnusedStubbingsFinder().getUnusedStubbings(mocks);
+            unused.reportUnused();
+        }
+    }
+
+    private static void emitWarnings(MockitoLogger logger, TestFinishedEvent event, Collection<Object> mocks) {
+        String testName = event.getTestClassInstance().getClass().getSimpleName() + "." + event.getTestMethodName();
+        if (event.getFailure() != null) {
+            //print stubbing mismatches only when there is a test failure
+            //to avoid false negatives. Give hint only when test fails.
+            new ArgMismatchFinder().getStubbingArgMismatches(mocks).format(testName, logger);
+        } else {
+            //print unused stubbings only when test succeeds to avoid reporting multiple problems and confusing users
+            new UnusedStubbingsFinder().getUnusedStubbings(mocks).format(testName, logger);
+        }
+    }
+
+    @Override
+    public void onMockCreated(Object mock, MockCreationSettings settings) {
+        this.mocks.put(mock, settings);
+
+        //It is not ideal that we modify the state of MockCreationSettings object
+        //MockCreationSettings is intended to be an immutable view of the creation settings
+        //In future, we should start passing MockSettings object to the creation listener
+        //TODO #793 - when completed, we should be able to get rid of the CreationSettings casting below
+        ((CreationSettings) settings).getStubbingLookupListeners().add(stubbingLookupListener);
+    }
+
+    public void setStrictness(Strictness strictness) {
+        this.currentStrictness = strictness;
+        this.stubbingLookupListener.setCurrentStrictness(strictness);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/UnnecessaryStubbingsReporter.java b/src/main/java/org/mockito/internal/junit/UnnecessaryStubbingsReporter.java
new file mode 100644
index 0000000..b14c85c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/UnnecessaryStubbingsReporter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.internal.exceptions.Reporter;
+import org.mockito.invocation.Invocation;
+import org.mockito.listeners.MockCreationListener;
+import org.mockito.mock.MockCreationSettings;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Reports unnecessary stubbings
+ */
+public class UnnecessaryStubbingsReporter implements MockCreationListener {
+
+    private List<Object> mocks = new LinkedList<Object>();
+
+    public void validateUnusedStubs(Class<?> testClass, RunNotifier notifier) {
+        Collection<Invocation> unused = new UnusedStubbingsFinder().getUnusedStubbingsByLocation(mocks);
+        if (unused.size() == 0) {
+            return; //whoa!!! All stubbings were used!
+        }
+
+        //Oups, there are unused stubbings
+        Description unnecessaryStubbings = Description.createTestDescription(testClass, "unnecessary Mockito stubbings");
+        notifier.fireTestFailure(new Failure(unnecessaryStubbings,
+                Reporter.formatUnncessaryStubbingException(testClass, unused)));
+    }
+
+    @Override
+    public void onMockCreated(Object mock, MockCreationSettings settings) {
+        mocks.add(mock);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/UnusedStubbings.java b/src/main/java/org/mockito/internal/junit/UnusedStubbings.java
new file mode 100644
index 0000000..474d4a6
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/UnusedStubbings.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import org.mockito.internal.exceptions.Reporter;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.invocation.Invocation;
+import org.mockito.stubbing.Stubbing;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Contains unused stubbings, knows how to format them
+ */
+public class UnusedStubbings {
+
+    private final Collection<? extends Stubbing> unused;
+
+    UnusedStubbings(Collection<? extends Stubbing> unused) {
+        this.unused = unused;
+    }
+
+    void format(String testName, MockitoLogger logger) {
+        if (unused.isEmpty()) {
+            return;
+        }
+
+        StubbingHint hint = new StubbingHint(testName);
+        int x = 1;
+        for (Stubbing candidate : unused) {
+            if (!candidate.wasUsed()) {
+                hint.appendLine(x++, ". Unused ", candidate.getInvocation().getLocation());
+            }
+        }
+        logger.log(hint.toString());
+    }
+
+    public int size() {
+        return unused.size();
+    }
+
+    public String toString() {
+        return unused.toString();
+    }
+
+    public void reportUnused() {
+        if (unused.size() > 0) {
+            List<Invocation> invocations = ListUtil.convert(unused, (ListUtil.Converter) new ListUtil.Converter<Stubbing, Invocation>() {
+                public Invocation convert(Stubbing s) {
+                    return s.getInvocation();
+                }
+            });
+
+
+            Reporter.unncessaryStubbingException(invocations);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/UnusedStubbingsFinder.java b/src/main/java/org/mockito/internal/junit/UnusedStubbingsFinder.java
new file mode 100644
index 0000000..715c393
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/UnusedStubbingsFinder.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import org.mockito.stubbing.Stubbing;
+import org.mockito.internal.invocation.finder.AllInvocationsFinder;
+import org.mockito.internal.util.collections.ListUtil.Filter;
+import org.mockito.invocation.Invocation;
+
+import java.util.*;
+
+import static org.mockito.internal.util.collections.ListUtil.filter;
+
+/**
+ * Finds unused stubbings
+ */
+public class UnusedStubbingsFinder {
+
+    /**
+     * Gets all unused stubbings for given set of mock objects, in order
+     */
+    public UnusedStubbings getUnusedStubbings(Iterable<Object> mocks) {
+        Set<Stubbing> stubbings = AllInvocationsFinder.findStubbings(mocks);
+
+        List<Stubbing> unused = filter(stubbings, new Filter<Stubbing>() {
+            public boolean isOut(Stubbing s) {
+                return s.wasUsed();
+            }
+        });
+
+        return new UnusedStubbings(unused);
+    }
+
+    /**
+     * Gets unused stubbings per location. This method is less accurate than {@link #getUnusedStubbings(Iterable)}.
+     * It considers that stubbings with the same location (e.g. ClassFile + line number) are the same.
+     * This is not completely accurate because a stubbing declared in a setup or constructor
+     * is created per each test method. Because those are different test methods,
+     * different mocks are created, different 'Invocation' instance is backing the 'Stubbing' instance.
+     * In certain scenarios (detecting unused stubbings by JUnit runner), we need this exact level of accuracy.
+     * Stubbing declared in constructor but realized in % of test methods is considered as 'used' stubbing.
+     * There are high level unit tests that demonstrate this scenario.
+     */
+    public Collection<Invocation> getUnusedStubbingsByLocation(Iterable<Object> mocks) {
+        Set<Stubbing> stubbings = AllInvocationsFinder.findStubbings(mocks);
+
+        //1st pass, collect all the locations of the stubbings that were used
+        //note that those are _not_ locations where the stubbings was used
+        Set<String> locationsOfUsedStubbings = new HashSet<String>();
+        for (Stubbing s : stubbings) {
+            if (s.wasUsed()) {
+                String location = s.getInvocation().getLocation().toString();
+                locationsOfUsedStubbings.add(location);
+            }
+        }
+
+        //2nd pass, collect unused stubbings by location
+        //If the location matches we assume the stubbing was used in at least one test method
+        //Also, using map to deduplicate reported unused stubbings
+        // if unused stubbing appear in the setup method / constructor we don't want to report it per each test case
+        Map<String, Invocation> out = new LinkedHashMap<String, Invocation>();
+        for (Stubbing s : stubbings) {
+            String location = s.getInvocation().getLocation().toString();
+            if (!locationsOfUsedStubbings.contains(location)) {
+                out.put(location, s.getInvocation());
+            }
+        }
+
+        return out.values();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/VerificationCollectorImpl.java b/src/main/java/org/mockito/internal/junit/VerificationCollectorImpl.java
new file mode 100644
index 0000000..7c19d35
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/VerificationCollectorImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.progress.MockingProgressImpl;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.junit.VerificationCollector;
+import org.mockito.verification.VerificationMode;
+import org.mockito.verification.VerificationStrategy;
+
+/**
+ * Mockito implementation of VerificationCollector.
+ */
+public class VerificationCollectorImpl implements VerificationCollector {
+
+    private StringBuilder builder;
+    private int numberOfFailures;
+
+    public VerificationCollectorImpl() {
+        this.resetBuilder();
+    }
+
+    public Statement apply(final Statement base, final Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                try {
+                    VerificationCollectorImpl.this.assertLazily();
+                    base.evaluate();
+                    VerificationCollectorImpl.this.collectAndReport();
+                } finally {
+                    // If base.evaluate() throws an error, we must explicitly reset the VerificationStrategy
+                    // to prevent subsequent tests to be assert lazily
+                    mockingProgress().setVerificationStrategy(MockingProgressImpl.getDefaultVerificationStrategy());
+                }
+            }
+        };
+    }
+
+    public void collectAndReport() throws MockitoAssertionError {
+        mockingProgress().setVerificationStrategy(MockingProgressImpl.getDefaultVerificationStrategy());
+
+        if (this.numberOfFailures > 0) {
+            String error = this.builder.toString();
+
+            this.resetBuilder();
+
+            throw new MockitoAssertionError(error);
+        }
+    }
+
+    public VerificationCollector assertLazily() {
+        mockingProgress().setVerificationStrategy(new VerificationStrategy() {
+            public VerificationMode maybeVerifyLazily(VerificationMode mode) {
+                return new VerificationWrapper(mode);
+            }
+        });
+        return this;
+    }
+
+    private void resetBuilder() {
+        this.builder = new StringBuilder()
+                .append("There were multiple verification failures:");
+        this.numberOfFailures = 0;
+    }
+
+    private void append(String message) {
+        this.numberOfFailures++;
+        this.builder.append('\n')
+                .append(this.numberOfFailures).append(". ")
+                .append(message.substring(1, message.length()));
+    }
+
+    private class VerificationWrapper implements VerificationMode {
+
+        private final VerificationMode delegate;
+
+        private VerificationWrapper(VerificationMode delegate) {
+            this.delegate = delegate;
+        }
+
+        public void verify(VerificationData data) {
+            try {
+                this.delegate.verify(data);
+            } catch (MockitoAssertionError error) {
+                VerificationCollectorImpl.this.append(error.getMessage());
+            }
+        }
+
+        public VerificationMode description(String description) {
+            throw new IllegalStateException("Should not fail in this mode");
+        }
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/junit/package-info.java b/src/main/java/org/mockito/internal/junit/package-info.java
new file mode 100644
index 0000000..932f181
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * JUnit integration support classes.
+ */
+package org.mockito.internal.junit;
diff --git a/src/main/java/org/mockito/internal/junit/util/JUnitFailureHacker.java b/src/main/java/org/mockito/internal/junit/util/JUnitFailureHacker.java
new file mode 100644
index 0000000..393867b
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/util/JUnitFailureHacker.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit.util;
+
+import java.lang.reflect.Field;
+import org.junit.runner.notification.Failure;
+import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
+
+@Deprecated
+public class JUnitFailureHacker {
+
+    public void appendWarnings(Failure failure, String warnings) {
+        if (isEmpty(warnings)) {
+            return;
+        }
+        //TODO: this has to protect the use in case jUnit changes and this internal state logic fails
+        Throwable throwable = (Throwable) getInternalState(failure, "fThrownException");
+
+        String newMessage = "contains both: actual test failure *and* Mockito warnings.\n" +
+                warnings + "\n *** The actual failure is because of: ***\n";
+
+        ExceptionIncludingMockitoWarnings e = new ExceptionIncludingMockitoWarnings(newMessage, throwable);
+        e.setStackTrace(throwable.getStackTrace());
+        setInternalState(failure, "fThrownException", e);
+    }
+
+    private boolean isEmpty(String warnings) {
+        return warnings == null || "".equals(warnings); // isEmpty() is in JDK 6+
+    }
+
+    private static Object getInternalState(Object target, String field) {
+        Class<?> c = target.getClass();
+        try {
+            Field f = getFieldFromHierarchy(c, field);
+            f.setAccessible(true);
+            return f.get(target);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to get internal state on a private field. Please report to mockito mailing list.", e);
+        }
+    }
+
+    private static void setInternalState(Object target, String field, Object value) {
+        Class<?> c = target.getClass();
+        try {
+            Field f = getFieldFromHierarchy(c, field);
+            f.setAccessible(true);
+            f.set(target, value);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to set internal state on a private field. Please report to mockito mailing list.", e);
+        }
+    }
+
+    private static Field getFieldFromHierarchy(Class<?> clazz, String field) {
+        Field f = getField(clazz, field);
+        while (f == null && clazz != Object.class) {
+            clazz = clazz.getSuperclass();
+            f = getField(clazz, field);
+        }
+        if (f == null) {
+            throw new RuntimeException(
+                    "You want me to get this field: '" + field +
+                            "' on this class: '" + clazz.getSimpleName() +
+                            "' but this field is not declared within the hierarchy of this class!");
+        }
+        return f;
+    }
+
+    private static Field getField(Class<?> clazz, String field) {
+        try {
+            return clazz.getDeclaredField(field);
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/junit/util/TestName.java b/src/main/java/org/mockito/internal/junit/util/TestName.java
new file mode 100644
index 0000000..69840d0
--- /dev/null
+++ b/src/main/java/org/mockito/internal/junit/util/TestName.java
@@ -0,0 +1,13 @@
+package org.mockito.internal.junit.util;
+
+import org.mockito.internal.junit.TestFinishedEvent;
+
+/**
+ * Provides test name
+ */
+public class TestName {
+
+    public static String getTestName(TestFinishedEvent event) {
+        return event.getTestClassInstance().getClass().getSimpleName() + "." + event.getTestMethodName();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/listeners/CollectCreatedMocks.java b/src/main/java/org/mockito/internal/listeners/CollectCreatedMocks.java
deleted file mode 100644
index 922ee23..0000000
--- a/src/main/java/org/mockito/internal/listeners/CollectCreatedMocks.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.listeners;

-

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public class CollectCreatedMocks implements MockingStartedListener {

-    

-    private final List toBeFilled;

-

-    public CollectCreatedMocks(List toBeFilled) {

-        this.toBeFilled = toBeFilled;

-    }

-

-    public void mockingStarted(Object mock, Class classToMock) {

-        toBeFilled.add(mock);

-    }

-}

diff --git a/src/main/java/org/mockito/internal/listeners/MockingProgressListener.java b/src/main/java/org/mockito/internal/listeners/MockingProgressListener.java
deleted file mode 100644
index 403088c..0000000
--- a/src/main/java/org/mockito/internal/listeners/MockingProgressListener.java
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.listeners;

-

-public interface MockingProgressListener {

-}

diff --git a/src/main/java/org/mockito/internal/listeners/MockingStartedListener.java b/src/main/java/org/mockito/internal/listeners/MockingStartedListener.java
deleted file mode 100644
index fd5cbe5..0000000
--- a/src/main/java/org/mockito/internal/listeners/MockingStartedListener.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.listeners;

-

-import org.mockito.MockSettings;

-

-@SuppressWarnings("unchecked")

-public interface MockingStartedListener extends MockingProgressListener {

-    

-    void mockingStarted(Object mock, Class classToMock);

-}

diff --git a/src/main/java/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java b/src/main/java/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java
deleted file mode 100644
index d73450a..0000000
--- a/src/main/java/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.listeners;

-

-import org.mockito.invocation.DescribedInvocation;

-import org.mockito.invocation.Invocation;

-import org.mockito.listeners.MethodInvocationReport;

-

-import static org.mockito.internal.matchers.Equality.areEqual;

-

-/**

- * Report on a method call

- */

-public class NotifiedMethodInvocationReport implements MethodInvocationReport {

-    private final Invocation invocation;

-    private final Object returnedValue;

-    private final Throwable throwable;

-

-

-    /**

-     * Build a new {@link org.mockito.listeners.MethodInvocationReport} with a return value.

-     *

-     *

-     * @param invocation Information on the method call

-     * @param returnedValue The value returned by the method invocation

-     */

-    public NotifiedMethodInvocationReport(Invocation invocation, Object returnedValue) {

-        this.invocation = invocation;

-        this.returnedValue = returnedValue;

-        this.throwable = null;

-    }

-

-    /**

-     * Build a new {@link org.mockito.listeners.MethodInvocationReport} with a return value.

-     *

-     *

-     * @param invocation Information on the method call

-     * @param throwable Tha throwable raised by the method invocation

-     */

-    public NotifiedMethodInvocationReport(Invocation invocation, Throwable throwable) {

-        this.invocation = invocation;

-        this.returnedValue = null;

-        this.throwable = throwable;

-    }

-

-    public DescribedInvocation getInvocation() {

-        return invocation;

-    }

-

-    public Object getReturnedValue() {

-        return returnedValue;

-    }

-

-    public Throwable getThrowable() {

-        return throwable;

-    }

-

-    public boolean threwException() {

-        return throwable != null;

-    }

-

-    public String getLocationOfStubbing() {

-        return (invocation.stubInfo() == null) ? null : invocation.stubInfo().stubbedAt().toString();

-    }

-

-

-    public boolean equals(Object o) {

-        if (this == o) return true;

-        if (o == null || getClass() != o.getClass()) return false;

-

-        NotifiedMethodInvocationReport that = (NotifiedMethodInvocationReport) o;

-

-        return areEqual(invocation, that.invocation) &&

-               areEqual(returnedValue, that.returnedValue) &&

-               areEqual(throwable, that.throwable);

-    }

-

-    public int hashCode() {

-        int result = invocation != null ? invocation.hashCode() : 0;

-        result = 31 * result + (returnedValue != null ? returnedValue.hashCode() : 0);

-        result = 31 * result + (throwable != null ? throwable.hashCode() : 0);

-        return result;

-    }

-}

diff --git a/src/main/java/org/mockito/internal/listeners/StubbingLookupListener.java b/src/main/java/org/mockito/internal/listeners/StubbingLookupListener.java
new file mode 100644
index 0000000..6f75ecc
--- /dev/null
+++ b/src/main/java/org/mockito/internal/listeners/StubbingLookupListener.java
@@ -0,0 +1,33 @@
+package org.mockito.internal.listeners;
+
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+/**
+ * Listens to attempts to look up stubbing answer for given mocks. This class is internal for now.
+ * <p>
+ * How does it work?
+ * When method is called on the mock object, Mockito looks for any answer (stubbing) declared on that mock.
+ * If the stubbed answer is found, that answer is invoked (value returned, thrown exception, etc.).
+ * If the answer is not found (e.g. that invocation was not stubbed on the mock), mock's default answer is used.
+ * This listener implementation is notified when Mockito looked up an answer for invocation on a mock.
+ * <p>
+ * If we make this interface a part of public API (and we should):
+ *  - make the implementation unified with InvocationListener (for example: common parent, marker interface MockObjectListener
+ *  single method for adding listeners so long they inherit from the parent)
+ *  - make the error handling strict
+ * so that Mockito provides decent message when listener fails due to poor implementation.
+ */
+public interface StubbingLookupListener {
+
+    /**
+     * Called by the framework when Mockito looked up an answer for invocation on a mock.
+     *
+     * TODO when making this public, we should have an event object instead of 2 arguments in the listener.
+     *
+     * @param invocation the invocation on the mock
+     * @param stubbingFound - can be null - it indicates that the invocation was not stubbed.
+     */
+    void onStubbingLookup(Invocation invocation, MatchableInvocation stubbingFound);
+
+}
diff --git a/src/main/java/org/mockito/internal/matchers/And.java b/src/main/java/org/mockito/internal/matchers/And.java
index 4ff068a..2c8f11c 100644
--- a/src/main/java/org/mockito/internal/matchers/And.java
+++ b/src/main/java/org/mockito/internal/matchers/And.java
@@ -6,40 +6,24 @@
 package org.mockito.internal.matchers;
 
 import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
 
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
 import org.mockito.ArgumentMatcher;
 
-@SuppressWarnings("unchecked")
-public class And extends ArgumentMatcher implements Serializable {
+@SuppressWarnings({ "unchecked", "serial","rawtypes" })
+public class And implements ArgumentMatcher<Object>, Serializable {
+    private ArgumentMatcher m1;
+    private ArgumentMatcher m2;
 
-    private static final long serialVersionUID = -4624719625691177501L;
-    private final List<Matcher> matchers;
-
-    public And(List<Matcher> matchers) {
-        this.matchers = matchers;
+    public And(ArgumentMatcher<?> m1, ArgumentMatcher<?> m2) {
+        this.m1 = m1;
+        this.m2 = m2;
     }
 
     public boolean matches(Object actual) {
-        for (Matcher matcher : matchers) {
-            if (!matcher.matches(actual)) {
-                return false;
-            }
-        }
-        return true;
+        return m1.matches(actual) && m2.matches(actual);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("and(");
-        for (Iterator<Matcher> it = matchers.iterator(); it.hasNext();) {
-            it.next().describeTo(description);
-            if (it.hasNext()) {
-                description.appendText(", ");
-            }
-        }
-        description.appendText(")");
+    public String toString() {
+        return "and("+m1+", "+m2+")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Any.java b/src/main/java/org/mockito/internal/matchers/Any.java
index 1876b38..f9f0069 100644
--- a/src/main/java/org/mockito/internal/matchers/Any.java
+++ b/src/main/java/org/mockito/internal/matchers/Any.java
@@ -7,22 +7,20 @@
 
 import java.io.Serializable;
 
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
-@SuppressWarnings("unchecked")
-public class Any extends ArgumentMatcher implements Serializable {
+public class Any implements ArgumentMatcher<Object>, VarargMatcher ,Serializable {
 
-    private static final long serialVersionUID = -4062420125651019029L;
-    public static final Any ANY = new Any();    
-    
-    private Any() {}
-    
+    public static final Any ANY = new Any();
+
+    private Any() {
+    }
+
     public boolean matches(Object actual) {
         return true;
     }
 
-    public void describeTo(Description description) {
-        description.appendText("<any>");
+    public String toString() {
+        return "<any>";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/AnyVararg.java b/src/main/java/org/mockito/internal/matchers/AnyVararg.java
deleted file mode 100644
index ce4cd02..0000000
--- a/src/main/java/org/mockito/internal/matchers/AnyVararg.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.matchers;

-

-import java.io.Serializable;

-

-import org.hamcrest.Matcher;

-import org.mockito.ArgumentMatcher;

-

-@SuppressWarnings("unchecked")

-public class AnyVararg extends ArgumentMatcher implements VarargMatcher, Serializable {

-

-    private static final long serialVersionUID = 1700721373094731555L;

-    public static final Matcher ANY_VARARG = new AnyVararg();

-

-    public boolean matches(Object arg) {

-        return true;

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/matchers/ArrayEquals.java b/src/main/java/org/mockito/internal/matchers/ArrayEquals.java
index c6cdf33..d647d1e 100644
--- a/src/main/java/org/mockito/internal/matchers/ArrayEquals.java
+++ b/src/main/java/org/mockito/internal/matchers/ArrayEquals.java
@@ -8,12 +8,8 @@
 import java.lang.reflect.Array;
 import java.util.Arrays;
 
-import org.hamcrest.Description;
-
 public class ArrayEquals extends Equals {
 
-    private static final long serialVersionUID = -7167812844261087583L;
-
     public ArrayEquals(Object wanted) {
         super(wanted);
     }
@@ -44,23 +40,25 @@
         return false;
     }
 
-    public void describeTo(Description description) {
+    public String toString() {
         if (getWanted() != null && getWanted().getClass().isArray()) {
-            appendArray(createObjectArray(getWanted()), description);
+            return appendArray(createObjectArray(getWanted()));
         } else {
-            super.describeTo(description);
+            return super.toString();
         }
     }
 
-    private void appendArray(Object[] array, Description description) {
-        description.appendText("[");
+    private String appendArray(Object[] array) {
+        //TODO SF overlap with ValuePrinter
+        StringBuilder out = new StringBuilder("[");
         for (int i = 0; i < array.length; i++) {
-            new Equals(array[i]).describeTo(description);
+            out.append(new Equals(array[i]).toString());
             if (i != array.length - 1) {
-                description.appendText(", ");
+                out.append(", ");
             }
         }
-        description.appendText("]");
+        out.append("]");
+        return out.toString();
     }
 
     public static Object[] createObjectArray(Object array) {
diff --git a/src/main/java/org/mockito/internal/matchers/CapturesArguments.java b/src/main/java/org/mockito/internal/matchers/CapturesArguments.java
index 5134abd..0c13853 100644
--- a/src/main/java/org/mockito/internal/matchers/CapturesArguments.java
+++ b/src/main/java/org/mockito/internal/matchers/CapturesArguments.java
@@ -2,11 +2,11 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.matchers;

-

-

-public interface CapturesArguments {

-

-    void captureFrom(Object argument);

-

-}

+package org.mockito.internal.matchers;
+
+
+public interface CapturesArguments {
+
+    void captureFrom(Object argument);
+
+}
diff --git a/src/main/java/org/mockito/internal/matchers/CapturingMatcher.java b/src/main/java/org/mockito/internal/matchers/CapturingMatcher.java
index 80759fa..8184f6d 100644
--- a/src/main/java/org/mockito/internal/matchers/CapturingMatcher.java
+++ b/src/main/java/org/mockito/internal/matchers/CapturingMatcher.java
@@ -1,51 +1,44 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.matchers;

-

-import org.hamcrest.Description;

-import org.mockito.ArgumentMatcher;

-import org.mockito.exceptions.Reporter;

-

-import java.io.Serializable;

-import java.util.LinkedList;

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public class CapturingMatcher<T> extends ArgumentMatcher<T> implements CapturesArguments, VarargMatcher, Serializable {

-    

-    private static final long serialVersionUID = 4274067078639307295L;

-    private final LinkedList<Object> arguments = new LinkedList<Object>();

-

-    /* (non-Javadoc)

-     * @see org.mockito.ArgumentMatcher#matches(java.lang.Object)

-     */

-    public boolean matches(Object argument) {

-        return true;

-    }    

-

-    /* (non-Javadoc)

-     * @see org.mockito.ArgumentMatcher#describeTo(org.hamcrest.Description)

-     */

-    public void describeTo(Description description) {

-        description.appendText("<Capturing argument>");

-    }

-

-    public T getLastValue() {

-        if (arguments.isEmpty()) {

-            new Reporter().noArgumentValueWasCaptured();

-            return null;

-        } else {

-            return (T) arguments.getLast();

-        }

-    }

-

-    public List<T> getAllValues() {

-        return (List) arguments;

-    }

-

-    public void captureFrom(Object argument) {

-        this.arguments.add(argument);

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import org.mockito.ArgumentMatcher;
+
+import static org.mockito.internal.exceptions.Reporter.noArgumentValueWasCaptured;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class CapturingMatcher<T> implements ArgumentMatcher<T>, CapturesArguments, VarargMatcher, Serializable {
+
+    private final LinkedList<Object> arguments = new LinkedList<Object>();
+
+    public boolean matches(Object argument) {
+        return true;
+    }
+
+    public String toString() {
+        return "<Capturing argument>";
+    }
+
+    public T getLastValue() {
+        if (arguments.isEmpty()) {
+            throw noArgumentValueWasCaptured();
+        }
+
+        return (T) arguments.getLast();
+
+    }
+
+    public List<T> getAllValues() {
+        return (List) arguments;
+    }
+
+    public void captureFrom(Object argument) {
+        this.arguments.add(argument);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/matchers/CompareEqual.java b/src/main/java/org/mockito/internal/matchers/CompareEqual.java
index 643d47c..eb21c46 100644
--- a/src/main/java/org/mockito/internal/matchers/CompareEqual.java
+++ b/src/main/java/org/mockito/internal/matchers/CompareEqual.java
@@ -9,9 +9,7 @@
 
 public class CompareEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
 
-    private static final long serialVersionUID = 2998586260452920429L;
-
-    public CompareEqual(Comparable<T> value) {
+    public CompareEqual(T value) {
         super(value);
     }
 
diff --git a/src/main/java/org/mockito/internal/matchers/CompareTo.java b/src/main/java/org/mockito/internal/matchers/CompareTo.java
index 428bf00..88f95cc 100644
--- a/src/main/java/org/mockito/internal/matchers/CompareTo.java
+++ b/src/main/java/org/mockito/internal/matchers/CompareTo.java
@@ -5,32 +5,36 @@
 
 package org.mockito.internal.matchers;
 
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
+import java.io.Serializable;
 
-public abstract class CompareTo<T extends Comparable<T>> extends ArgumentMatcher<T> {
-    private final Comparable<T> wanted;
+public abstract class CompareTo<T extends Comparable<T>> implements ArgumentMatcher<T>, Serializable {
+    private final T wanted;
 
-    public CompareTo(Comparable<T> value) {
+    public CompareTo(T value) {
         this.wanted = value;
     }
 
-    @SuppressWarnings("unchecked")
-    public boolean matches(Object actual) {
-        
-        if(!(actual instanceof Comparable)) {
+    @Override
+    public final boolean matches(T actual) {
+        if (actual == null) {
             return false;
         }
-        
-        return matchResult(((Comparable) actual).compareTo(wanted));
+        if (!actual.getClass().isInstance(wanted)){
+            return false;
+        }
+
+        int result = actual.compareTo(wanted);
+        return matchResult(result);
     }
 
-    public void describeTo(Description description) {
-        description.appendText(getName() + "(" + wanted + ")");
+    @Override
+    public final String toString() {
+        return getName() + "(" + wanted + ")";
     }
-    
+
     protected abstract String getName();
-    
+
     protected abstract boolean matchResult(int result);
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Contains.java b/src/main/java/org/mockito/internal/matchers/Contains.java
index 5901c08..daa7608 100644
--- a/src/main/java/org/mockito/internal/matchers/Contains.java
+++ b/src/main/java/org/mockito/internal/matchers/Contains.java
@@ -5,26 +5,24 @@
 
 package org.mockito.internal.matchers;
 
-import java.io.Serializable;
-
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
+import java.io.Serializable;
 
-public class Contains extends ArgumentMatcher<String> implements Serializable {
 
-    private static final long serialVersionUID = -1909837398271763801L;
+public class Contains implements ArgumentMatcher<String>, Serializable {
+
     private final String substring;
 
     public Contains(String substring) {
         this.substring = substring;
     }
 
-    public boolean matches(Object actual) {
-        return actual != null && ((String) actual).contains(substring);
+    public boolean matches(String actual) {
+        return actual != null && actual.contains(substring);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("contains(\"" + substring + "\")");
+    public String toString() {
+        return "contains(\"" + substring + "\")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInfo.java b/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInfo.java
new file mode 100644
index 0000000..3b69fbc
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInfo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+/**
+ * Intended to use in certain ArgumentMatchers.
+ * When ArgumentMatcher fails, chance is that the actual object has the same output of toString() than
+ * the wanted object. This looks weird when failures are reported.
+ * Therefore when matcher fails but toString() yields the same outputs,
+ * we will try to use the {@link #toStringWithType()} method.
+ */
+public interface ContainsExtraTypeInfo {
+
+    /**
+     * Returns more verbose description of the object which include type information
+     */
+    String toStringWithType();
+
+    /**
+     * Checks if target target has matching type.
+     * If the type matches, there is no point in rendering result from {@link #toStringWithType()}
+     */
+    boolean typeMatches(Object target);
+}
diff --git a/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInformation.java b/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInformation.java
deleted file mode 100644
index 137a610..0000000
--- a/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInformation.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.matchers;

-

-import java.io.Serializable;

-

-import org.hamcrest.SelfDescribing;

-

-public interface ContainsExtraTypeInformation extends Serializable {

-    SelfDescribing withExtraTypeInfo();

-

-    boolean typeMatches(Object object);

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/matchers/EndsWith.java b/src/main/java/org/mockito/internal/matchers/EndsWith.java
index 3c92f92..2abde2b 100644
--- a/src/main/java/org/mockito/internal/matchers/EndsWith.java
+++ b/src/main/java/org/mockito/internal/matchers/EndsWith.java
@@ -7,24 +7,21 @@
 
 import java.io.Serializable;
 
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
+public class EndsWith implements ArgumentMatcher<String>, Serializable {
 
-public class EndsWith extends ArgumentMatcher<String> implements Serializable {
-
-    private static final long serialVersionUID = 8556443228350129421L;
     private final String suffix;
 
     public EndsWith(String suffix) {
         this.suffix = suffix;
     }
 
-    public boolean matches(Object actual) {
-        return actual != null && ((String) actual).endsWith(suffix);
+    public boolean matches(String actual) {
+        return actual != null && actual.endsWith(suffix);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("endsWith(\"" + suffix + "\")");
+    public String toString() {
+        return "endsWith(\"" + suffix + "\")";
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/matchers/Equality.java b/src/main/java/org/mockito/internal/matchers/Equality.java
index 0791441..9702550 100644
--- a/src/main/java/org/mockito/internal/matchers/Equality.java
+++ b/src/main/java/org/mockito/internal/matchers/Equality.java
@@ -2,42 +2,42 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.matchers;

-

-import java.lang.reflect.Array;

-

-//stolen from hamcrest because I didn't want to have more dependency than Matcher class 

-public class Equality {

-

-    public static boolean areEqual(Object o1, Object o2) {

-        if (o1 == o2 ) {

-            return true;

-	} else if (o1 == null || o2 == null) {

-            return o1 == null && o2 == null;

-        } else if (isArray(o1)) {

-            return isArray(o2) && areArraysEqual(o1, o2);

-        } else {

-            return o1.equals(o2);

-        }

-    }

-

-    static boolean areArraysEqual(Object o1, Object o2) {

-        return areArrayLengthsEqual(o1, o2)

-                && areArrayElementsEqual(o1, o2);

-    }

-

-    static boolean areArrayLengthsEqual(Object o1, Object o2) {

-        return Array.getLength(o1) == Array.getLength(o2);

-    }

-

-    static boolean areArrayElementsEqual(Object o1, Object o2) {

-        for (int i = 0; i < Array.getLength(o1); i++) {

-            if (!areEqual(Array.get(o1, i), Array.get(o2, i))) return false;

-        }

-        return true;

-    }

-

-    static boolean isArray(Object o) {

-        return o.getClass().isArray();

-    }

-}
\ No newline at end of file
+package org.mockito.internal.matchers;
+
+import java.lang.reflect.Array;
+
+//stolen from hamcrest because I didn't want to have more dependency than Matcher class
+public class Equality {
+
+    public static boolean areEqual(Object o1, Object o2) {
+        if (o1 == o2 ) {
+            return true;
+    } else if (o1 == null || o2 == null) {
+            return false;
+        } else if (isArray(o1)) {
+            return isArray(o2) && areArraysEqual(o1, o2);
+        } else {
+            return o1.equals(o2);
+        }
+    }
+
+    static boolean areArraysEqual(Object o1, Object o2) {
+        return areArrayLengthsEqual(o1, o2)
+                && areArrayElementsEqual(o1, o2);
+    }
+
+    static boolean areArrayLengthsEqual(Object o1, Object o2) {
+        return Array.getLength(o1) == Array.getLength(o2);
+    }
+
+    static boolean areArrayElementsEqual(Object o1, Object o2) {
+        for (int i = 0; i < Array.getLength(o1); i++) {
+            if (!areEqual(Array.get(o1, i), Array.get(o2, i))) return false;
+        }
+        return true;
+    }
+
+    static boolean isArray(Object o) {
+        return o.getClass().isArray();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/matchers/Equals.java b/src/main/java/org/mockito/internal/matchers/Equals.java
index b712622..ba9f37f 100644
--- a/src/main/java/org/mockito/internal/matchers/Equals.java
+++ b/src/main/java/org/mockito/internal/matchers/Equals.java
@@ -5,15 +5,13 @@
 
 package org.mockito.internal.matchers;
 
-import org.hamcrest.Description;
-import org.hamcrest.SelfDescribing;
 import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.text.ValuePrinter;
 
 import java.io.Serializable;
 
-public class Equals extends ArgumentMatcher<Object> implements ContainsExtraTypeInformation, Serializable {
+public class Equals implements ArgumentMatcher<Object>, ContainsExtraTypeInfo, Serializable {
 
-    private static final long serialVersionUID = -3395637450058086891L;
     private final Object wanted;
 
     public Equals(Object wanted) {
@@ -24,22 +22,12 @@
         return Equality.areEqual(this.wanted, actual);
     }
 
-    public void describeTo(Description description) {
-        description.appendText(describe(wanted));
+    public String toString() {
+        return describe(wanted);
     }
 
-    public String describe(Object object) {
-        return quoting() + object + quoting();
-    }
-
-    private String quoting() {
-        if (wanted instanceof String) {
-            return "\"";
-        } else if (wanted instanceof Character) {
-            return "'";
-        } else {
-            return "";
-        }
+    private String describe(Object object) {
+        return ValuePrinter.print(object);
     }
 
     protected final Object getWanted() {
@@ -60,14 +48,11 @@
         return 1;
     }
 
-    public SelfDescribing withExtraTypeInfo() {
-        return new SelfDescribing() {
-            public void describeTo(Description description) {
-                description.appendText(describe("("+ wanted.getClass().getSimpleName() +") " + wanted));
-            }};
+    public String toStringWithType() {
+        return "("+ wanted.getClass().getSimpleName() +") " + describe(wanted);
     }
 
-    public boolean typeMatches(Object object) {
-        return wanted != null && object != null && object.getClass() == wanted.getClass();
+    public boolean typeMatches(Object target) {
+        return wanted != null && target != null && target.getClass() == wanted.getClass();
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/matchers/EqualsWithDelta.java b/src/main/java/org/mockito/internal/matchers/EqualsWithDelta.java
index 7e99b08..d5d8e19 100644
--- a/src/main/java/org/mockito/internal/matchers/EqualsWithDelta.java
+++ b/src/main/java/org/mockito/internal/matchers/EqualsWithDelta.java
@@ -5,17 +5,13 @@
 
 package org.mockito.internal.matchers;
 
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
 import java.io.Serializable;
 
-
-public class EqualsWithDelta extends ArgumentMatcher<Number> implements Serializable {
-    private static final long serialVersionUID = 5066980489920383664L;
+public class EqualsWithDelta implements ArgumentMatcher<Number>, Serializable {
 
     private final Number wanted;
-
     private final Number delta;
 
     public EqualsWithDelta(Number value, Number delta) {
@@ -23,8 +19,7 @@
         this.delta = delta;
     }
 
-    public boolean matches(Object actual) {
-        Number actualNumber = (Number) actual;
+    public boolean matches(Number actual) {
         if (wanted == null ^ actual == null) {
             return false;
         }
@@ -33,12 +28,12 @@
             return true;
         }
 
-        return wanted.doubleValue() - delta.doubleValue() <= actualNumber.doubleValue()
-                && actualNumber.doubleValue() <= wanted.doubleValue()
+        return wanted.doubleValue() - delta.doubleValue() <= actual.doubleValue()
+                && actual.doubleValue() <= wanted.doubleValue()
                         + delta.doubleValue();
     }
 
-    public void describeTo(Description description) {
-        description.appendText("eq(" + wanted + ", " + delta + ")");
+    public String toString() {
+        return "eq(" + wanted + ", " + delta + ")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Find.java b/src/main/java/org/mockito/internal/matchers/Find.java
index 9c07796..178c444 100644
--- a/src/main/java/org/mockito/internal/matchers/Find.java
+++ b/src/main/java/org/mockito/internal/matchers/Find.java
@@ -8,23 +8,21 @@
 import java.io.Serializable;
 import java.util.regex.Pattern;
 
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
-public class Find extends ArgumentMatcher<String> implements Serializable {
+public class Find implements ArgumentMatcher<String>, Serializable {
 
-    private static final long serialVersionUID = 8895781429480404872L;
     private final String regex;
 
     public Find(String regex) {
         this.regex = regex;
     }
 
-    public boolean matches(Object actual) {
-        return actual != null && Pattern.compile(regex).matcher((String) actual).find();
+    public boolean matches(String actual) {
+        return actual != null && Pattern.compile(regex).matcher(actual).find();
     }
 
-    public void describeTo(Description description) {
-        description.appendText("find(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")");
+    public String toString() {
+        return "find(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")";
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/matchers/GreaterOrEqual.java b/src/main/java/org/mockito/internal/matchers/GreaterOrEqual.java
index a67cb1a..f1c8ff2 100644
--- a/src/main/java/org/mockito/internal/matchers/GreaterOrEqual.java
+++ b/src/main/java/org/mockito/internal/matchers/GreaterOrEqual.java
@@ -9,9 +9,7 @@
 
 public class GreaterOrEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
 
-    private static final long serialVersionUID = 87695769061286092L;
-
-    public GreaterOrEqual(Comparable<T> value) {
+    public GreaterOrEqual(T value) {
         super(value);
     }
 
diff --git a/src/main/java/org/mockito/internal/matchers/GreaterThan.java b/src/main/java/org/mockito/internal/matchers/GreaterThan.java
index 9130acf..46497c1 100644
--- a/src/main/java/org/mockito/internal/matchers/GreaterThan.java
+++ b/src/main/java/org/mockito/internal/matchers/GreaterThan.java
@@ -9,9 +9,7 @@
 
 public class GreaterThan<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
 
-    private static final long serialVersionUID = 7446529803235604408L;
-
-    public GreaterThan(Comparable<T> value) {
+    public GreaterThan(T value) {
         super(value);
     }
 
@@ -23,5 +21,5 @@
     @Override
     protected boolean matchResult(int result) {
         return result > 0;
-    }    
+    }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/InstanceOf.java b/src/main/java/org/mockito/internal/matchers/InstanceOf.java
index f976d8f..2876aa2 100644
--- a/src/main/java/org/mockito/internal/matchers/InstanceOf.java
+++ b/src/main/java/org/mockito/internal/matchers/InstanceOf.java
@@ -5,26 +5,46 @@
 
 package org.mockito.internal.matchers;
 
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.util.Primitives;
+
 import java.io.Serializable;
 
-import org.hamcrest.Description;
-import org.mockito.ArgumentMatcher;
 
+public class InstanceOf implements ArgumentMatcher<Object>, Serializable {
 
-public class InstanceOf extends ArgumentMatcher<Object> implements Serializable {
-
-    private static final long serialVersionUID = 517358915876138366L;
     private final Class<?> clazz;
+    private String description;
 
     public InstanceOf(Class<?> clazz) {
+        this(clazz, "isA(" + clazz.getCanonicalName() + ")");
+    }
+
+    public InstanceOf(Class<?> clazz, String describedAs) {
         this.clazz = clazz;
+        this.description = describedAs;
     }
 
     public boolean matches(Object actual) {
-        return (actual != null) && clazz.isAssignableFrom(actual.getClass());
+        return (actual != null) &&
+                (Primitives.isAssignableFromWrapper(actual.getClass(), clazz)
+                        || clazz.isAssignableFrom(actual.getClass()));
     }
 
-    public void describeTo(Description description) {
-        description.appendText("isA(" + clazz.getName() + ")");
+    public String toString() {
+        return description;
     }
+
+    public static class VarArgAware extends InstanceOf implements VarargMatcher {
+
+        public VarArgAware(Class<?> clazz) {
+            super(clazz);
+        }
+
+        public VarArgAware(Class<?> clazz, String describedAs) {
+            super(clazz, describedAs);
+        }
+    }
+
+
 }
diff --git a/src/main/java/org/mockito/internal/matchers/LessOrEqual.java b/src/main/java/org/mockito/internal/matchers/LessOrEqual.java
index 82a09c1..1b3d737 100644
--- a/src/main/java/org/mockito/internal/matchers/LessOrEqual.java
+++ b/src/main/java/org/mockito/internal/matchers/LessOrEqual.java
@@ -9,9 +9,7 @@
 
 public class LessOrEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
 
-    private static final long serialVersionUID = -6648773374429103565L;
-
-    public LessOrEqual(Comparable<T> value) {
+    public LessOrEqual(T value) {
         super(value);
     }
 
diff --git a/src/main/java/org/mockito/internal/matchers/LessThan.java b/src/main/java/org/mockito/internal/matchers/LessThan.java
index 19d5a80..c0c931e 100644
--- a/src/main/java/org/mockito/internal/matchers/LessThan.java
+++ b/src/main/java/org/mockito/internal/matchers/LessThan.java
@@ -9,9 +9,7 @@
 
 public class LessThan<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
 
-    private static final long serialVersionUID = -133860804462310942L;
-
-    public LessThan(Comparable<T> value) {
+    public LessThan(T value) {
         super(value);
     }
 
diff --git a/src/main/java/org/mockito/internal/matchers/LocalizedMatcher.java b/src/main/java/org/mockito/internal/matchers/LocalizedMatcher.java
index 7ba456b..00b47de 100644
--- a/src/main/java/org/mockito/internal/matchers/LocalizedMatcher.java
+++ b/src/main/java/org/mockito/internal/matchers/LocalizedMatcher.java
@@ -1,69 +1,29 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.matchers;

-

-import org.hamcrest.BaseMatcher;

-import org.hamcrest.Description;

-import org.hamcrest.Matcher;

-import org.hamcrest.SelfDescribing;

-import org.mockito.internal.debugging.LocationImpl;

-import org.mockito.invocation.Location;

-

-import java.io.Serializable;

-

-@SuppressWarnings("unchecked")

-public class LocalizedMatcher extends BaseMatcher

-        implements Matcher, ContainsExtraTypeInformation, CapturesArguments, MatcherDecorator, Serializable {

-

-    private static final long serialVersionUID = 6748641229659825725L;

-    private final Matcher actualMatcher;

-    private final Location location;

-

-    public LocalizedMatcher(Matcher actualMatcher) {

-        this.actualMatcher = actualMatcher;

-        this.location = new LocationImpl();

-    }

-

-    public boolean matches(Object item) {

-        return actualMatcher.matches(item);

-    }

-

-    public void describeTo(Description description) {

-        actualMatcher.describeTo(description);

-    }

-

-    public Location getLocation() {

-        return location;

-    }

-    

-    @Override

-    public String toString() {

-        return "Localized: " + this.actualMatcher;

-    }

-

-    public SelfDescribing withExtraTypeInfo() {

-        if (actualMatcher instanceof ContainsExtraTypeInformation) {

-            return ((ContainsExtraTypeInformation) actualMatcher).withExtraTypeInfo();

-        } else {

-            return this;

-        }

-    }

-

-    public boolean typeMatches(Object object) {

-        return actualMatcher instanceof ContainsExtraTypeInformation

-                && ((ContainsExtraTypeInformation) actualMatcher).typeMatches(object);

-    }

-

-    public void captureFrom(Object argument) {

-        if (actualMatcher instanceof CapturesArguments) {

-            ((CapturesArguments) actualMatcher).captureFrom(argument);

-        }

-    }

-

-    //TODO: refactor other 'delegated interfaces' to use the MatcherDecorator feature

-    public Matcher getActualMatcher() {

-        return actualMatcher;

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.invocation.Location;
+
+@SuppressWarnings("unchecked")
+public class LocalizedMatcher {
+
+    private final ArgumentMatcher<?> matcher;
+    private final Location location;
+
+    public LocalizedMatcher(ArgumentMatcher<?> matcher) {
+        this.matcher = matcher;
+        this.location = new LocationImpl();
+    }
+
+    public Location getLocation() {
+        return location;
+    }
+
+    public ArgumentMatcher<?> getMatcher() {
+        return matcher;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/matchers/MatcherDecorator.java b/src/main/java/org/mockito/internal/matchers/MatcherDecorator.java
deleted file mode 100644
index aa01160..0000000
--- a/src/main/java/org/mockito/internal/matchers/MatcherDecorator.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.matchers;

-

-import java.io.Serializable;

-

-import org.hamcrest.Matcher;

-

-@SuppressWarnings("unchecked")

-public interface MatcherDecorator extends Serializable {

-    Matcher getActualMatcher();

-}

diff --git a/src/main/java/org/mockito/internal/matchers/MatchersPrinter.java b/src/main/java/org/mockito/internal/matchers/MatchersPrinter.java
deleted file mode 100644
index f0505bf..0000000
--- a/src/main/java/org/mockito/internal/matchers/MatchersPrinter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.matchers;

-

-import java.util.LinkedList;

-import java.util.List;

-

-import org.hamcrest.Description;

-import org.hamcrest.Matcher;

-import org.hamcrest.SelfDescribing;

-import org.hamcrest.StringDescription;

-import org.mockito.internal.reporting.PrintSettings;

-

-@SuppressWarnings("unchecked")

-public class MatchersPrinter {

-    

-    public String getArgumentsLine(List<Matcher> matchers, PrintSettings printSettings) {

-        Description result = new StringDescription();

-        result.appendList("(", ", ", ");", applyPrintSettings(matchers, printSettings));

-        return result.toString();

-    }

-

-    public String getArgumentsBlock(List<Matcher> matchers, PrintSettings printSettings) {

-        Description result = new StringDescription();

-        result.appendList("(\n    ", ",\n    ", "\n);", applyPrintSettings(matchers, printSettings));

-        return result.toString();

-    }

-

-    private List<SelfDescribing> applyPrintSettings(List<Matcher> matchers, PrintSettings printSettings) {

-        List<SelfDescribing> withPrintSettings = new LinkedList<SelfDescribing>();

-        int i = 0;

-        for (final Matcher matcher : matchers) {

-            if (matcher instanceof ContainsExtraTypeInformation && printSettings.extraTypeInfoFor(i)) {

-                withPrintSettings.add(((ContainsExtraTypeInformation) matcher).withExtraTypeInfo());

-            } else {

-                withPrintSettings.add(matcher);

-            }

-            i++;

-        }

-        return withPrintSettings;

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/matchers/Matches.java b/src/main/java/org/mockito/internal/matchers/Matches.java
index f7dd560..2a15c47 100644
--- a/src/main/java/org/mockito/internal/matchers/Matches.java
+++ b/src/main/java/org/mockito/internal/matchers/Matches.java
@@ -6,26 +6,26 @@
 package org.mockito.internal.matchers;
 
 import java.io.Serializable;
-
-import org.hamcrest.Description;
+import java.util.regex.Pattern;
 import org.mockito.ArgumentMatcher;
 
+public class Matches implements ArgumentMatcher<Object>, Serializable {
 
-public class Matches extends ArgumentMatcher<Object> implements Serializable {
-
-    private static final long serialVersionUID = 8787704593379472029L;
-    private final String regex;
+    private final Pattern pattern;
 
     public Matches(String regex) {
-        this.regex = regex;
+        this(Pattern.compile(regex));
+    }
+
+    public Matches(Pattern pattern) {
+        this.pattern = pattern;
     }
 
     public boolean matches(Object actual) {
-        return (actual instanceof String) && ((String) actual).matches(regex);
+        return (actual instanceof String) && pattern.matcher((String) actual).matches();
     }
 
-    public void describeTo(Description description) {
-        description.appendText("matches(\"" + regex.replaceAll("\\\\", "\\\\\\\\")
-                + "\")");
+    public String toString() {
+        return "matches(\"" + pattern.pattern().replaceAll("\\\\", "\\\\\\\\") + "\")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Not.java b/src/main/java/org/mockito/internal/matchers/Not.java
index 70d581a..1cece9d 100644
--- a/src/main/java/org/mockito/internal/matchers/Not.java
+++ b/src/main/java/org/mockito/internal/matchers/Not.java
@@ -5,29 +5,24 @@
 
 package org.mockito.internal.matchers;
 
-import java.io.Serializable;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
 import org.mockito.ArgumentMatcher;
 
-@SuppressWarnings("unchecked")
-public class Not extends ArgumentMatcher implements Serializable {
+import java.io.Serializable;
 
-    private static final long serialVersionUID = 4627373642333593264L;
-    private final Matcher first;
+@SuppressWarnings({ "unchecked", "serial","rawtypes" })
+public class Not implements ArgumentMatcher<Object>, Serializable {
 
-    public Not(Matcher first) {
-        this.first = first;
+    private final ArgumentMatcher matcher;
+
+    public Not(ArgumentMatcher<?> matcher) {
+        this.matcher = matcher;
     }
 
     public boolean matches(Object actual) {
-        return !first.matches(actual);
+        return !matcher.matches(actual);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("not(");
-        first.describeTo(description);
-        description.appendText(")");
+    public String toString() {
+        return "not(" + matcher + ")";
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/matchers/NotNull.java b/src/main/java/org/mockito/internal/matchers/NotNull.java
index 9453ea5..1b4b36d 100644
--- a/src/main/java/org/mockito/internal/matchers/NotNull.java
+++ b/src/main/java/org/mockito/internal/matchers/NotNull.java
@@ -5,26 +5,22 @@
 
 package org.mockito.internal.matchers;
 
-import java.io.Serializable;
-
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
+import java.io.Serializable;
 
-public class NotNull extends ArgumentMatcher<Object> implements Serializable {
+public class NotNull implements ArgumentMatcher<Object>, Serializable {
 
-    private static final long serialVersionUID = 7278261081285153228L;
     public static final NotNull NOT_NULL = new NotNull();
-    
+
     private NotNull() {
-        
     }
-    
+
     public boolean matches(Object actual) {
         return actual != null;
     }
 
-    public void describeTo(Description description) {
-        description.appendText("notNull()");
+    public String toString() {
+        return "notNull()";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Null.java b/src/main/java/org/mockito/internal/matchers/Null.java
index 31d95db..650a606 100644
--- a/src/main/java/org/mockito/internal/matchers/Null.java
+++ b/src/main/java/org/mockito/internal/matchers/Null.java
@@ -5,15 +5,12 @@
 
 package org.mockito.internal.matchers;
 
-import java.io.Serializable;
-
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
+import java.io.Serializable;
 
-public class Null extends ArgumentMatcher<Object> implements Serializable {
+public class Null implements ArgumentMatcher<Object>, Serializable {
 
-    private static final long serialVersionUID = 2823082637424390314L;
     public static final Null NULL = new Null();
 
     private Null() {
@@ -23,7 +20,7 @@
         return actual == null;
     }
 
-    public void describeTo(Description description) {
-        description.appendText("isNull()");
+    public String toString() {
+        return "isNull()";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Or.java b/src/main/java/org/mockito/internal/matchers/Or.java
index 5b739b7..803a533 100644
--- a/src/main/java/org/mockito/internal/matchers/Or.java
+++ b/src/main/java/org/mockito/internal/matchers/Or.java
@@ -6,40 +6,24 @@
 package org.mockito.internal.matchers;
 
 import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
 
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
 import org.mockito.ArgumentMatcher;
 
-@SuppressWarnings("unchecked")
-public class Or extends ArgumentMatcher implements Serializable {
+@SuppressWarnings({ "unchecked", "serial","rawtypes" })
+public class Or implements ArgumentMatcher<Object>, Serializable {
+    private final ArgumentMatcher m1;
+    private final ArgumentMatcher m2;
 
-    private static final long serialVersionUID = 5888739035212283087L;
-    private final List<Matcher> matchers;
-
-    public Or(List<Matcher> matchers) {
-        this.matchers = matchers;
+    public Or(ArgumentMatcher<?> m1, ArgumentMatcher<?> m2) {
+        this.m1 = m1;
+        this.m2 = m2;
     }
 
     public boolean matches(Object actual) {
-        for (Matcher matcher : matchers) {
-            if (matcher.matches(actual)) {
-                return true;
-            }
-        }
-        return false;
+        return m1.matches(actual) || m2.matches(actual);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("or(");
-        for (Iterator<Matcher> it = matchers.iterator(); it.hasNext();) {
-            it.next().describeTo(description);
-            if (it.hasNext()) {
-                description.appendText(", ");
-            }
-        }
-        description.appendText(")");
+    public String toString() {
+        return "or("+m1+", "+m2+")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/Same.java b/src/main/java/org/mockito/internal/matchers/Same.java
index 7ab6da3..b834376 100644
--- a/src/main/java/org/mockito/internal/matchers/Same.java
+++ b/src/main/java/org/mockito/internal/matchers/Same.java
@@ -5,15 +5,13 @@
 
 package org.mockito.internal.matchers;
 
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.text.ValuePrinter;
 
 import java.io.Serializable;
 
+public class Same implements ArgumentMatcher<Object>, Serializable {
 
-public class Same extends ArgumentMatcher<Object> implements Serializable {
-
-    private static final long serialVersionUID = -1226959355938572597L;
     private final Object wanted;
 
     public Same(Object wanted) {
@@ -24,19 +22,7 @@
         return wanted == actual;
     }
 
-    public void describeTo(Description description) {
-        description.appendText("same(");
-        appendQuoting(description);
-        description.appendText("" + wanted);
-        appendQuoting(description);
-        description.appendText(")");
-    }
-
-    private void appendQuoting(Description description) {
-        if (wanted instanceof String) {
-            description.appendText("\"");
-        } else if (wanted instanceof Character) {
-            description.appendText("'");
-        }
+    public String toString() {
+        return "same(" + ValuePrinter.print(wanted) + ")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/StartsWith.java b/src/main/java/org/mockito/internal/matchers/StartsWith.java
index 3557ff0..f89c2c0 100644
--- a/src/main/java/org/mockito/internal/matchers/StartsWith.java
+++ b/src/main/java/org/mockito/internal/matchers/StartsWith.java
@@ -5,26 +5,23 @@
 
 package org.mockito.internal.matchers;
 
-import java.io.Serializable;
-
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
+import java.io.Serializable;
 
-public class StartsWith extends ArgumentMatcher<String> implements Serializable {
+public class StartsWith implements ArgumentMatcher<String>, Serializable {
 
-    private static final long serialVersionUID = -5978092285707998431L;
     private final String prefix;
 
     public StartsWith(String prefix) {
         this.prefix = prefix;
     }
 
-    public boolean matches(Object actual) {
-        return actual != null && ((String) actual).startsWith(prefix);
+    public boolean matches(String actual) {
+        return actual != null && actual.startsWith(prefix);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("startsWith(\"" + prefix + "\")");
+    public String toString() {
+        return "startsWith(\"" + prefix + "\")";
     }
 }
diff --git a/src/main/java/org/mockito/internal/matchers/VarargCapturingMatcher.java b/src/main/java/org/mockito/internal/matchers/VarargCapturingMatcher.java
deleted file mode 100644
index cc978e0..0000000
--- a/src/main/java/org/mockito/internal/matchers/VarargCapturingMatcher.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.mockito.internal.matchers;
-
-import org.hamcrest.Description;
-import org.mockito.ArgumentMatcher;
-import org.mockito.exceptions.Reporter;
-
-import java.io.Serializable;
-import java.lang.reflect.Array;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-
-@SuppressWarnings("unchecked")
-public class VarargCapturingMatcher<T> extends ArgumentMatcher<T> implements CapturesArguments, VarargMatcher, Serializable {
-    private static final long serialVersionUID = 4057053345838026645L;
-    private final LinkedList<List<T>> arguments = new LinkedList<List<T>>();
-
-    public boolean matches(Object argument) {
-        return true;
-    }
-
-    public void describeTo(Description description) {
-        description.appendText("<Capturing variable argument>");
-    }
-
-    public List<T> getLastVarargs() {
-        if (arguments.isEmpty()) {
-            new Reporter().noArgumentValueWasCaptured();
-            return null;
-        } else {
-            return arguments.getLast();
-        }
-    }
-
-    public List<List<T>> getAllVarargs() {
-        return arguments;
-    }
-
-    public void captureFrom(Object varArgArray) {
-        List<T> vararg = unpackAsList(varArgArray);
-        this.arguments.add(vararg);
-    }
-
-    private List<T> unpackAsList(Object varArgArray) {
-        if (varArgArray instanceof Object[]) {
-            return Arrays.asList((T[]) varArgArray);
-        } else if (varArgArray.getClass().isArray()) {
-            Object[] primitiveArray = new Object[Array.getLength(varArgArray)];
-            for (int i = 0; i < primitiveArray.length; i++) {
-                primitiveArray[i] = Array.get(varArgArray, i);
-            }
-            return Arrays.asList((T[]) primitiveArray);
-        } else {
-            return Collections.singletonList((T) varArgArray);
-        }
-    }
-}
diff --git a/src/main/java/org/mockito/internal/matchers/VarargMatcher.java b/src/main/java/org/mockito/internal/matchers/VarargMatcher.java
index 5e04dcc..fc843f6 100644
--- a/src/main/java/org/mockito/internal/matchers/VarargMatcher.java
+++ b/src/main/java/org/mockito/internal/matchers/VarargMatcher.java
@@ -2,9 +2,13 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.matchers;

-

-import java.io.Serializable;

-

-public interface VarargMatcher extends Serializable {

-}

+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+/**
+ * Internal interface that informs Mockito that the matcher is intended to capture varargs.
+ * This information is needed when mockito collects the arguments.
+ */
+public interface VarargMatcher extends Serializable {
+}
diff --git a/src/main/java/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java b/src/main/java/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java
index 76704f9..92662c8 100644
--- a/src/main/java/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java
+++ b/src/main/java/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java
@@ -75,7 +75,7 @@
  */
 @SuppressWarnings("unchecked")
 class EqualsBuilder {
-    
+
     /**
      * If the fields tested are equals.
      * The default value is <code>true</code>.
@@ -186,9 +186,9 @@
      * @param reflectUpToClass  the superclass to reflect up to (inclusive),
      *  may be <code>null</code>
      * @return <code>true</code> if the two Objects have tested equals.
-     * @since 2.0
+     * @since 2.1.0
      */
-    public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+    public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class<?> reflectUpToClass) {
         return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, null);
     }
 
@@ -216,9 +216,9 @@
      *  may be <code>null</code>
      * @param excludeFields  array of field names to exclude from testing
      * @return <code>true</code> if the two Objects have tested equals.
-     * @since 2.0
+     * @since 2.1.0
      */
-    public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass,
+    public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class<?> reflectUpToClass,
             String[] excludeFields) {
         if (lhs == rhs) {
             return true;
@@ -226,13 +226,13 @@
         if (lhs == null || rhs == null) {
             return false;
         }
-        // Find the leaf class since there may be transients in the leaf 
+        // Find the leaf class since there may be transients in the leaf
         // class or in classes between the leaf and root.
-        // If we are not testing transients or a subclass has no ivars, 
+        // If we are not testing transients or a subclass has no ivars,
         // then a subclass can test equals to a superclass.
-        Class lhsClass = lhs.getClass();
-        Class rhsClass = rhs.getClass();
-        Class testClass;
+        Class<?> lhsClass = lhs.getClass();
+        Class<?> rhsClass = rhs.getClass();
+        Class<?> testClass;
         if (lhsClass.isInstance(rhs)) {
             testClass = lhsClass;
             if (!rhsClass.isInstance(lhs)) {
@@ -258,7 +258,7 @@
             }
         } catch (IllegalArgumentException e) {
             // In this case, we tried to test a subclass vs. a superclass and
-            // the subclass has ivars or the ivars are transient and 
+            // the subclass has ivars or the ivars are transient and
             // we are testing transients.
             // If a subclass has ivars that we are trying to test them, we get an
             // exception and we know that the objects are not equal.
@@ -270,7 +270,7 @@
     /**
      * <p>Appends the fields and values defined by the given object of the
      * given Class.</p>
-     * 
+     *
      * @param lhs  the left hand object
      * @param rhs  the right hand object
      * @param clazz  the class to append details of
@@ -281,12 +281,12 @@
     private static void reflectionAppend(
         Object lhs,
         Object rhs,
-        Class clazz,
+        Class<?> clazz,
         EqualsBuilder builder,
         boolean useTransients,
         String[] excludeFields) {
         Field[] fields = clazz.getDeclaredFields();
-        List excludedFieldList = excludeFields != null ? Arrays.asList(excludeFields) : Collections.EMPTY_LIST;
+        List<String> excludedFieldList = excludeFields != null ? Arrays.asList(excludeFields) : Collections.<String>emptyList();
         AccessibleObject.setAccessible(fields, true);
         for (int i = 0; i < fields.length && builder.isEquals; i++) {
             Field f = fields[i];
@@ -312,7 +312,7 @@
      *
      * @param superEquals  the result of calling <code>super.equals()</code>
      * @return EqualsBuilder - used to chain calls.
-     * @since 2.0
+     * @since 2.1.0
      */
     public EqualsBuilder appendSuper(boolean superEquals) {
         isEquals &= superEquals;
@@ -340,7 +340,7 @@
             this.setEquals(false);
             return this;
         }
-        Class lhsClass = lhs.getClass();
+        Class<?> lhsClass = lhs.getClass();
         if (!lhsClass.isArray()) {
             if (lhs instanceof java.math.BigDecimal && rhs instanceof java.math.BigDecimal) {
                 isEquals = (((java.math.BigDecimal) lhs).compareTo((java.math.BigDecimal) rhs) == 0);
@@ -349,9 +349,9 @@
                 isEquals = lhs.equals(rhs);
             }
         } else if (lhs.getClass() != rhs.getClass()) {
-            // Here when we compare different dimensions, for example: a boolean[][] to a boolean[] 
+            // Here when we compare different dimensions, for example: a boolean[][] to a boolean[]
             this.setEquals(false);
-        
+
         // 'Switch' on type of array, to dispatch to the correct handler
         // This handles multi dimensional arrays of the same depth
         } else if (lhs instanceof long[]) {
@@ -381,7 +381,7 @@
      * <p>
      * Test if two <code>long</code> s are equal.
      * </p>
-     * 
+     *
      * @param lhs
      *                  the left hand <code>long</code>
      * @param rhs
@@ -784,7 +784,7 @@
 
     /**
      * Sets the <code>isEquals</code> value.
-     * 
+     *
      * @param isEquals The value to set.
      * @since 2.1
      */
diff --git a/src/main/java/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java b/src/main/java/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java
index 9568cd6..2787e97 100644
--- a/src/main/java/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java
+++ b/src/main/java/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java
@@ -5,13 +5,12 @@
 
 package org.mockito.internal.matchers.apachecommons;
 
-import java.io.Serializable;
-
-import org.hamcrest.Description;
 import org.mockito.ArgumentMatcher;
 
-public class ReflectionEquals extends ArgumentMatcher<Object> implements Serializable {
-    private static final long serialVersionUID = 2022780425116330014L;
+import java.io.Serializable;
+
+public class ReflectionEquals implements ArgumentMatcher<Object>, Serializable {
+
     private final Object wanted;
     private final String[] excludeFields;
 
@@ -24,7 +23,7 @@
         return EqualsBuilder.reflectionEquals(wanted, actual, excludeFields);
     }
 
-    public void describeTo(Description description) {
-        description.appendText("refEq(" + wanted + ")");
+    public String toString() {
+        return "refEq(" + wanted + ")";
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt b/src/main/java/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt
index 753842b..3d4b8d7 100644
--- a/src/main/java/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt
+++ b/src/main/java/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt
@@ -1,201 +1,206 @@
-                                 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

+====
+    Copyright (c) 2016 Mockito contributors
+    This program is made available under the terms of the MIT License.
+====
+
+                                 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.
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/matchers/apachecommons/package-info.java b/src/main/java/org/mockito/internal/matchers/apachecommons/package-info.java
new file mode 100644
index 0000000..0ce7a2c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/apachecommons/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Argument matchers that use Apache Commons Lang reflection-equality.
+ */
+package org.mockito.internal.matchers.apachecommons;
diff --git a/src/main/java/org/mockito/internal/matchers/apachecommons/package.html b/src/main/java/org/mockito/internal/matchers/apachecommons/package.html
deleted file mode 100644
index bbb72c8..0000000
--- a/src/main/java/org/mockito/internal/matchers/apachecommons/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Argument matchers that use Apache Commons Lang reflection-equality.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/matchers/package-info.java b/src/main/java/org/mockito/internal/matchers/package-info.java
new file mode 100644
index 0000000..fbc39fa
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Argument matchers for verification and stubbing.
+ */
+package org.mockito.internal.matchers;
diff --git a/src/main/java/org/mockito/internal/matchers/package.html b/src/main/java/org/mockito/internal/matchers/package.html
deleted file mode 100644
index 26b6f88..0000000
--- a/src/main/java/org/mockito/internal/matchers/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Argument matchers for verification and stubbing.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/matchers/text/ArrayIterator.java b/src/main/java/org/mockito/internal/matchers/text/ArrayIterator.java
new file mode 100644
index 0000000..6fe2309
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/text/ArrayIterator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers.text;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+
+/**
+ * Inspired on hamcrest, internal package class,
+ * TODO add specific unit tests instead of relying on higher level unit tests
+ */
+class ArrayIterator implements Iterator<Object> {
+
+    private final Object array;
+    private int currentIndex = 0;
+
+    public ArrayIterator(Object array) {
+        if (array == null) {
+            //TODO extract a small utility for null-checking
+            throw new IllegalArgumentException("Expected array instance but got null");
+        }
+        if (!array.getClass().isArray()) {
+            throw new IllegalArgumentException("Expected array but got object of type: "
+                    + array.getClass() + ", the object: " + array.toString());
+        }
+        this.array = array;
+    }
+
+    public boolean hasNext() {
+        return currentIndex < Array.getLength(array);
+    }
+
+    public Object next() {
+        return Array.get(array, currentIndex++);
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("cannot remove items from an array");
+    }
+}
diff --git a/src/main/java/org/mockito/internal/matchers/text/FormattedText.java b/src/main/java/org/mockito/internal/matchers/text/FormattedText.java
new file mode 100644
index 0000000..72f94ca
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/text/FormattedText.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers.text;
+
+/**
+ * Contains text that has already been formatted
+ * and hence it does not need any formatting (like quotes around string, etc.)
+ */
+class FormattedText {
+
+    private final String text;
+
+    public FormattedText(String text) {
+        this.text = text;
+    }
+
+    public String getText() {
+        return text;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/matchers/text/MatcherToString.java b/src/main/java/org/mockito/internal/matchers/text/MatcherToString.java
new file mode 100644
index 0000000..f67b868
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/text/MatcherToString.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers.text;
+
+import static org.mockito.internal.util.ObjectMethodsGuru.isToStringMethod;
+import static org.mockito.internal.util.StringUtil.decamelizeMatcher;
+
+import java.lang.reflect.Method;
+import org.mockito.ArgumentMatcher;
+
+/**
+ * Provides better toString() text for matcher that don't have toString() method declared.
+ */
+class MatcherToString {
+
+    /**
+     * Attempts to provide more descriptive toString() for given matcher.
+     * Searches matcher class hierarchy for toString() method. If it is found it will be used.
+     * If no toString() is defined for the matcher hierarchy,
+     * uses decamelized class name instead of default Object.toString().
+     * This way we can promote meaningful names for custom matchers.
+     *
+     * @param matcher
+     * @return
+     */
+    static String toString(ArgumentMatcher<?> matcher) {
+        Class<?> cls = matcher.getClass();
+        while(cls != Object.class) {
+            Method[] methods = cls.getDeclaredMethods();
+            for (Method m : methods) {
+                if(isToStringMethod(m)) {
+                    return matcher.toString();
+                }
+            }
+            cls = cls.getSuperclass();
+        }
+        return decamelizeMatcher(matcher.getClass().getSimpleName());
+    }
+
+
+}
diff --git a/src/main/java/org/mockito/internal/matchers/text/MatchersPrinter.java b/src/main/java/org/mockito/internal/matchers/text/MatchersPrinter.java
new file mode 100644
index 0000000..98194fc
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/text/MatchersPrinter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers.text;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.ContainsExtraTypeInfo;
+import org.mockito.internal.reporting.PrintSettings;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class MatchersPrinter {
+
+    public String getArgumentsLine(List<ArgumentMatcher> matchers, PrintSettings printSettings) {
+        Iterator args = applyPrintSettings(matchers, printSettings);
+        return ValuePrinter.printValues("(", ", ", ");", args);
+    }
+
+    public String getArgumentsBlock(List<ArgumentMatcher> matchers, PrintSettings printSettings) {
+        Iterator args = applyPrintSettings(matchers, printSettings);
+        return ValuePrinter.printValues("(\n    ", ",\n    ", "\n);", args);
+    }
+
+    private Iterator<FormattedText> applyPrintSettings(List<ArgumentMatcher> matchers, PrintSettings printSettings) {
+        List<FormattedText> out = new LinkedList<FormattedText>();
+        int i = 0;
+        for (final ArgumentMatcher matcher : matchers) {
+            if (matcher instanceof ContainsExtraTypeInfo && printSettings.extraTypeInfoFor(i)) {
+                out.add(new FormattedText(((ContainsExtraTypeInfo) matcher).toStringWithType()));
+            } else {
+                out.add(new FormattedText(MatcherToString.toString(matcher)));
+            }
+            i++;
+        }
+        return out.iterator();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/matchers/text/ValuePrinter.java b/src/main/java/org/mockito/internal/matchers/text/ValuePrinter.java
new file mode 100644
index 0000000..f741cbc
--- /dev/null
+++ b/src/main/java/org/mockito/internal/matchers/text/ValuePrinter.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers.text;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import static java.lang.String.valueOf;
+
+/**
+ * Prints a Java object value in a way humans can read it neatly.
+ * Inspired on hamcrest. Used for printing arguments in verification errors.
+ */
+public class ValuePrinter {
+
+    private ValuePrinter(){}
+
+    /**
+     * Prints given value so that it is neatly readable by humans.
+     * Handles explosive toString() implementations.
+     */
+    public static String print(Object value) {
+        if (value == null) {
+            return "null";
+        }
+        if (value instanceof String) {
+            return '"' + value.toString() + '"';
+        }
+        if (value instanceof Character) {
+            return printChar((Character) value);
+        }
+        if (value instanceof Long) {
+            return value + "L";
+        }
+        if (value instanceof Double) {
+            return value + "d";
+        }
+        if (value instanceof Float) {
+            return value + "f";
+        }
+        if (value instanceof Short) {
+            return "(short) " + value;
+        }
+        if (value instanceof Byte) {
+            return String.format("(byte) 0x%02X", (Byte) value);
+        }
+        if (value instanceof Map) {
+            return printMap((Map<?, ?>) value);
+        }
+        if (value.getClass().isArray()) {
+            return printValues("[", ", ", "]", new ArrayIterator(value));
+        }
+        if (value instanceof FormattedText) {
+            return (((FormattedText) value).getText());
+        }
+
+        return descriptionOf(value);
+    }
+
+    private static String printMap(Map<?,?> map) {
+        StringBuilder result = new StringBuilder();
+        Iterator<? extends Map.Entry<?, ?>> iterator = map.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<?, ?> entry = iterator.next();
+            result.append(print(entry.getKey())).append(" = ").append(print(entry.getValue()));
+            if (iterator.hasNext()) {
+                result.append(", ");
+            }
+        }
+        return "{" + result.toString() + "}";
+    }
+
+    /**
+     * Print values in a nice format, e.g. (1, 2, 3)
+     *
+     * @param start the beginning of the values, e.g. "("
+     * @param separator the separator of values, e.g. ", "
+     * @param end the end of the values, e.g. ")"
+     * @param values the values to print
+     *
+     * @return neatly formatted value list
+     */
+    public static String printValues(String start, String separator, String end, Iterator<?> values) {
+        if(start == null){
+            start = "(";
+        }
+        if (separator == null){
+            separator = ",";
+        }
+        if (end == null){
+            end = ")";
+        }
+
+        StringBuilder sb = new StringBuilder(start);
+        while(values.hasNext()) {
+            sb.append(print(values.next()));
+            if (values.hasNext()) {
+                sb.append(separator);
+            }
+        }
+        return sb.append(end).toString();
+    }
+
+    private static String printChar(char value) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('\'');
+        switch (value) {
+            case '"':
+                sb.append("\\\"");
+                break;
+            case '\n':
+                sb.append("\\n");
+                break;
+            case '\r':
+                sb.append("\\r");
+                break;
+            case '\t':
+                sb.append("\\t");
+                break;
+            default:
+                sb.append(value);
+        }
+        sb.append('\'');
+        return sb.toString();
+    }
+
+    private static String descriptionOf(Object value) {
+        try {
+            return valueOf(value);
+        }
+        catch (Exception e) {
+            return value.getClass().getName() + "@" + Integer.toHexString(value.hashCode());
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/package-info.java b/src/main/java/org/mockito/internal/package-info.java
new file mode 100644
index 0000000..b6c4c80
--- /dev/null
+++ b/src/main/java/org/mockito/internal/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Internal classes, not to be used by clients.
+ *
+ * Subject to change at any time without notice.
+ */
+package org.mockito.internal;
diff --git a/src/main/java/org/mockito/internal/package.html b/src/main/java/org/mockito/internal/package.html
deleted file mode 100644
index bd8f199..0000000
--- a/src/main/java/org/mockito/internal/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Internal classes, not to be used by clients.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorage.java b/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorage.java
index 3beee43..572b9d4 100644
--- a/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorage.java
+++ b/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorage.java
@@ -2,28 +2,28 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.progress;

-

-import org.hamcrest.Matcher;

-import org.mockito.internal.matchers.LocalizedMatcher;

-

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public interface ArgumentMatcherStorage {

-

-    HandyReturnValues reportMatcher(Matcher matcher);

-

-    List<LocalizedMatcher> pullLocalizedMatchers();

-

-    HandyReturnValues reportAnd();

-

-    HandyReturnValues reportNot();

-

-    HandyReturnValues reportOr();

-

-    void validateState();

-

-    void reset();

-

-}
\ No newline at end of file
+package org.mockito.internal.progress;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.LocalizedMatcher;
+
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public interface ArgumentMatcherStorage {
+
+    void reportMatcher(ArgumentMatcher<?> matcher);
+
+    List<LocalizedMatcher> pullLocalizedMatchers();
+
+    void reportAnd();
+
+    void reportNot();
+
+    void reportOr();
+
+    void validateState();
+
+    void reset();
+
+}
diff --git a/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java b/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java
index c8d68b6..6e8dd24 100644
--- a/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java
+++ b/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java
@@ -5,121 +5,93 @@
 
 package org.mockito.internal.progress;
 
-import org.hamcrest.Matcher;
-import org.mockito.exceptions.Reporter;
+import org.mockito.ArgumentMatcher;
 import org.mockito.internal.matchers.And;
 import org.mockito.internal.matchers.LocalizedMatcher;
 import org.mockito.internal.matchers.Not;
 import org.mockito.internal.matchers.Or;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Stack;
+import static java.util.Collections.emptyList;
+import static org.mockito.internal.exceptions.Reporter.incorrectUseOfAdditionalMatchers;
+import static org.mockito.internal.exceptions.Reporter.misplacedArgumentMatcher;
+import static org.mockito.internal.exceptions.Reporter.reportNoSubMatchersFound;
 
-@SuppressWarnings("unchecked")
+import java.util.*;
+
 public class ArgumentMatcherStorageImpl implements ArgumentMatcherStorage {
 
-    public static final int TWO_SUB_MATCHERS = 2;
-    public static final int ONE_SUB_MATCHER = 1;
+    private static final int TWO_SUB_MATCHERS = 2;
+    private static final int ONE_SUB_MATCHER = 1;
     private final Stack<LocalizedMatcher> matcherStack = new Stack<LocalizedMatcher>();
-    
-    /* (non-Javadoc)
-     * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportMatcher(org.hamcrest.Matcher)
-     */
-    public HandyReturnValues reportMatcher(Matcher matcher) {
+
+    public void reportMatcher(ArgumentMatcher<?> matcher) {
         matcherStack.push(new LocalizedMatcher(matcher));
-        return new HandyReturnValues();
     }
 
-    /* (non-Javadoc)
-     * @see org.mockito.internal.progress.ArgumentMatcherStorage#pullLocalizedMatchers()
-     */
     public List<LocalizedMatcher> pullLocalizedMatchers() {
         if (matcherStack.isEmpty()) {
-            return Collections.emptyList();
+            return emptyList();
         }
-        
-        List<LocalizedMatcher> matchers = new ArrayList<LocalizedMatcher>(matcherStack);
-        matcherStack.clear();
-        return (List) matchers;
+
+        List<LocalizedMatcher> lastMatchers = resetStack();
+        return lastMatchers;
     }
 
-    /* (non-Javadoc)
-    * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportAnd()
-    */
-    public HandyReturnValues reportAnd() {
+    public void reportAnd() {
         assertStateFor("And(?)", TWO_SUB_MATCHERS);
-        And and = new And(popLastArgumentMatchers(TWO_SUB_MATCHERS));
-        matcherStack.push(new LocalizedMatcher(and));
-        return new HandyReturnValues();
+
+        ArgumentMatcher<?> m1 = popMatcher();
+        ArgumentMatcher<?> m2 = popMatcher();
+
+        reportMatcher(new And(m1, m2));
     }
 
-    /* (non-Javadoc)
-     * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportOr()
-     */
-    public HandyReturnValues reportOr() {
+    public void reportOr() {
         assertStateFor("Or(?)", TWO_SUB_MATCHERS);
-        Or or = new Or(popLastArgumentMatchers(TWO_SUB_MATCHERS));
-        matcherStack.push(new LocalizedMatcher(or));
-        return new HandyReturnValues();
+
+        ArgumentMatcher<?> m1 = popMatcher();
+        ArgumentMatcher<?> m2 = popMatcher();
+
+        reportMatcher(new Or(m1, m2));
     }
 
-    /* (non-Javadoc)
-     * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportNot()
-     */
-    public HandyReturnValues reportNot() {
+    public void reportNot() {
         assertStateFor("Not(?)", ONE_SUB_MATCHER);
-        Not not = new Not(popLastArgumentMatchers(ONE_SUB_MATCHER).get(0));
-        matcherStack.push(new LocalizedMatcher(not));
-        return new HandyReturnValues();
+
+        ArgumentMatcher<?> m = popMatcher();
+
+        reportMatcher(new Not(m));
     }
 
-    private void assertStateFor(String additionalMatcherName, int subMatchersCount) {
-        assertMatchersFoundFor(additionalMatcherName);
-        assertIncorrectUseOfAdditionalMatchers(additionalMatcherName, subMatchersCount);
-    }
-
-    private List<Matcher> popLastArgumentMatchers(int count) {
-        List<Matcher> result = new LinkedList<Matcher>();
-        result.addAll(matcherStack.subList(matcherStack.size() - count, matcherStack.size()));
-        for (int i = 0; i < count; i++) {
-            matcherStack.pop();
-        }
-        return result;
-    }
-
-    private void assertMatchersFoundFor(String additionalMatcherName) {
-        if (matcherStack.isEmpty()) {
-            matcherStack.clear();
-            new Reporter().reportNoSubMatchersFound(additionalMatcherName);
-        }
-    }
-
-    private void assertIncorrectUseOfAdditionalMatchers(String additionalMatcherName, int count) {
-        if(matcherStack.size() < count) {
-            ArrayList<LocalizedMatcher> lastMatchers = new ArrayList<LocalizedMatcher>(matcherStack);
-            matcherStack.clear();
-            new Reporter().incorrectUseOfAdditionalMatchers(additionalMatcherName, count, lastMatchers);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.mockito.internal.progress.ArgumentMatcherStorage#validateState()
-     */
     public void validateState() {
         if (!matcherStack.isEmpty()) {
-            ArrayList lastMatchers = new ArrayList<LocalizedMatcher>(matcherStack);
-            matcherStack.clear();
-            new Reporter().misplacedArgumentMatcher(lastMatchers);
+            List<LocalizedMatcher> lastMatchers = resetStack();
+            throw misplacedArgumentMatcher(lastMatchers);
         }
     }
 
-    /* (non-Javadoc)
-     * @see org.mockito.internal.progress.ArgumentMatcherStorage#reset()
-     */
     public void reset() {
         matcherStack.clear();
     }
-}
\ No newline at end of file
+
+    private void assertStateFor(String additionalMatcherName, int subMatchersCount) {
+        if (matcherStack.isEmpty()) {
+            throw reportNoSubMatchersFound(additionalMatcherName);
+        }
+        if (matcherStack.size() < subMatchersCount) {
+            List<LocalizedMatcher> lastMatchers = resetStack();
+            throw incorrectUseOfAdditionalMatchers(additionalMatcherName, subMatchersCount, lastMatchers);
+        }
+    }
+
+    private ArgumentMatcher<?> popMatcher() {
+        return matcherStack.pop().getMatcher();
+    }
+
+    private List<LocalizedMatcher> resetStack() {
+        ArrayList<LocalizedMatcher> lastMatchers = new ArrayList<LocalizedMatcher>(matcherStack);
+        reset();
+        return lastMatchers;
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/progress/HandyReturnValues.java b/src/main/java/org/mockito/internal/progress/HandyReturnValues.java
deleted file mode 100644
index 3556621..0000000
--- a/src/main/java/org/mockito/internal/progress/HandyReturnValues.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.progress;

-

-import java.util.*;

-

-import static org.mockito.internal.util.Primitives.defaultValueForPrimitiveOrWrapper;

-import static org.mockito.internal.util.Primitives.isPrimitiveOrWrapper;

-

-@SuppressWarnings("unchecked")

-public class HandyReturnValues {

-

-    public byte returnZero() {

-        return 0;

-    }

-

-    public char returnChar() {

-        return 0;

-    }

-

-    public <T> T returnNull() {

-        return null;

-    }

-

-    public boolean returnFalse() {

-        return false;

-    }

-

-    public String returnString() {

-        return "";

-    }

-

-    public <T> T returnFor(Class<T> clazz) {

-        // explicitly return null if type is not a primitive or a wrapper

-        if (isPrimitiveOrWrapper(clazz)) {

-            return defaultValueForPrimitiveOrWrapper(clazz);

-        } 

-        return null;

-    }

-

-    public Map returnMap() {

-        return new HashMap();

-    }

-

-    public List returnList() {

-        return new LinkedList();

-    }

-

-    public Set returnSet() {

-        return new HashSet();

-    }

-

-    public <T> T returnFor(T instance) {

-        return instance == null ? null : (T) returnFor(instance.getClass());

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/progress/IOngoingStubbing.java b/src/main/java/org/mockito/internal/progress/IOngoingStubbing.java
deleted file mode 100644
index aeb5784..0000000
--- a/src/main/java/org/mockito/internal/progress/IOngoingStubbing.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.progress;

-

-

-/**

- * Marking interface to be removed when DeprecatedOngoingStubbing gets deleted

- */

-public interface IOngoingStubbing {}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/progress/MockingProgress.java b/src/main/java/org/mockito/internal/progress/MockingProgress.java
index 36fc582..47bc900 100644
--- a/src/main/java/org/mockito/internal/progress/MockingProgress.java
+++ b/src/main/java/org/mockito/internal/progress/MockingProgress.java
@@ -5,17 +5,21 @@
 
 package org.mockito.internal.progress;
 
-import org.mockito.MockSettings;
-import org.mockito.internal.listeners.MockingProgressListener;
-import org.mockito.invocation.Invocation;
+import java.util.Set;
+import org.mockito.listeners.MockitoListener;
+import org.mockito.listeners.VerificationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.OngoingStubbing;
 import org.mockito.verification.VerificationMode;
+import org.mockito.verification.VerificationStrategy;
 
-@SuppressWarnings("unchecked")
 public interface MockingProgress {
-    
-    void reportOngoingStubbing(IOngoingStubbing iOngoingStubbing);
 
-    IOngoingStubbing pullOngoingStubbing();
+    void reportOngoingStubbing(OngoingStubbing<?> ongoingStubbing);
+
+    OngoingStubbing<?> pullOngoingStubbing();
+
+    Set<VerificationListener> verificationListeners();
 
     void verificationStarted(VerificationMode verificationMode);
 
@@ -23,8 +27,8 @@
 
     void stubbingStarted();
 
-    void stubbingCompleted(Invocation invocation);
-    
+    void stubbingCompleted();
+
     void validateState();
 
     void reset();
@@ -36,8 +40,19 @@
     void resetOngoingStubbing();
 
     ArgumentMatcherStorage getArgumentMatcherStorage();
-    
-    void mockingStarted(Object mock, Class classToMock);
 
-    void setListener(MockingProgressListener listener);
-}
\ No newline at end of file
+    void mockingStarted(Object mock, MockCreationSettings settings);
+
+    void addListener(MockitoListener listener);
+
+    void removeListener(MockitoListener listener);
+
+    void setVerificationStrategy(VerificationStrategy strategy);
+
+    VerificationMode maybeVerifyLazily(VerificationMode mode);
+
+    /**
+     * Removes all listeners added via {@link #addListener(MockitoListener)}.
+     */
+    void clearListeners();
+}
diff --git a/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java b/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java
index e9235d9..a0f8c66 100644
--- a/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java
+++ b/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java
@@ -5,37 +5,72 @@
 
 package org.mockito.internal.progress;
 
-import org.mockito.exceptions.Reporter;
 import org.mockito.internal.configuration.GlobalConfiguration;
 import org.mockito.internal.debugging.Localized;
 import org.mockito.internal.debugging.LocationImpl;
-import org.mockito.internal.listeners.MockingProgressListener;
-import org.mockito.internal.listeners.MockingStartedListener;
-import org.mockito.invocation.Invocation;
+import org.mockito.internal.exceptions.Reporter;
 import org.mockito.invocation.Location;
+import org.mockito.listeners.MockCreationListener;
+import org.mockito.listeners.MockitoListener;
+import org.mockito.listeners.VerificationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.OngoingStubbing;
 import org.mockito.verification.VerificationMode;
+import org.mockito.verification.VerificationStrategy;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static org.mockito.internal.exceptions.Reporter.unfinishedStubbing;
+import static org.mockito.internal.exceptions.Reporter.unfinishedVerificationException;
 
 @SuppressWarnings("unchecked")
 public class MockingProgressImpl implements MockingProgress {
-    
-    private final Reporter reporter = new Reporter();
+
     private final ArgumentMatcherStorage argumentMatcherStorage = new ArgumentMatcherStorageImpl();
-    
-    IOngoingStubbing iOngoingStubbing;
+
+    private OngoingStubbing<?> ongoingStubbing;
     private Localized<VerificationMode> verificationMode;
     private Location stubbingInProgress = null;
-    private MockingProgressListener listener;
+    private VerificationStrategy verificationStrategy;
+    private final Set<MockitoListener> listeners = new LinkedHashSet<MockitoListener>();
 
-    public void reportOngoingStubbing(IOngoingStubbing iOngoingStubbing) {
-        this.iOngoingStubbing = iOngoingStubbing;
+    public MockingProgressImpl() {
+        this.verificationStrategy = getDefaultVerificationStrategy();
     }
 
-    public IOngoingStubbing pullOngoingStubbing() {
-        IOngoingStubbing temp = iOngoingStubbing;
-        iOngoingStubbing = null;
+    public static VerificationStrategy getDefaultVerificationStrategy() {
+        return new VerificationStrategy() {
+            public VerificationMode maybeVerifyLazily(VerificationMode mode) {
+                return mode;
+            }
+        };
+    }
+
+    public void reportOngoingStubbing(OngoingStubbing iOngoingStubbing) {
+        this.ongoingStubbing = iOngoingStubbing;
+    }
+
+    public OngoingStubbing<?> pullOngoingStubbing() {
+        OngoingStubbing<?> temp = ongoingStubbing;
+        ongoingStubbing = null;
         return temp;
     }
-    
+
+    @Override
+    public Set<VerificationListener> verificationListeners() {
+        final LinkedHashSet<VerificationListener> verificationListeners = new LinkedHashSet<VerificationListener>();
+
+        for (MockitoListener listener : listeners) {
+            if (listener instanceof VerificationListener) {
+                verificationListeners.add((VerificationListener) listener);
+            }
+        }
+
+        return verificationListeners;
+    }
+
+
     public void verificationStarted(VerificationMode verify) {
         validateState();
         resetOngoingStubbing();
@@ -46,14 +81,14 @@
      * @see org.mockito.internal.progress.MockingProgress#resetOngoingStubbing()
      */
     public void resetOngoingStubbing() {
-        iOngoingStubbing = null;
+        ongoingStubbing = null;
     }
 
     public VerificationMode pullVerificationMode() {
         if (verificationMode == null) {
             return null;
         }
-        
+
         VerificationMode temp = verificationMode.getObject();
         verificationMode = null;
         return temp;
@@ -66,12 +101,12 @@
 
     public void validateState() {
         validateMostStuff();
-        
+
         //validate stubbing:
         if (stubbingInProgress != null) {
             Location temp = stubbingInProgress;
             stubbingInProgress = null;
-            reporter.unfinishedStubbing(temp);
+            throw unfinishedStubbing(temp);
         }
     }
 
@@ -83,18 +118,18 @@
         if (verificationMode != null) {
             Location location = verificationMode.getLocation();
             verificationMode = null;
-            reporter.unfinishedVerificationException(location);
+            throw unfinishedVerificationException(location);
         }
 
         getArgumentMatcherStorage().validateState();
     }
 
-    public void stubbingCompleted(Invocation invocation) {
+    public void stubbingCompleted() {
         stubbingInProgress = null;
     }
-    
+
     public String toString() {
-        return  "iOngoingStubbing: " + iOngoingStubbing + 
+        return  "iOngoingStubbing: " + ongoingStubbing +
         ", verificationMode: " + verificationMode +
         ", stubbingInProgress: " + stubbingInProgress;
     }
@@ -109,14 +144,48 @@
         return argumentMatcherStorage;
     }
 
-    public void mockingStarted(Object mock, Class classToMock) {
-        if (listener instanceof MockingStartedListener) {
-            ((MockingStartedListener) listener).mockingStarted(mock, classToMock);
+    public void mockingStarted(Object mock, MockCreationSettings settings) {
+        for (MockitoListener listener : listeners) {
+            if (listener instanceof MockCreationListener) {
+                ((MockCreationListener) listener).onMockCreated(mock, settings);
+            }
         }
         validateMostStuff();
     }
 
-    public void setListener(MockingProgressListener listener) {
-        this.listener = listener;
+    public void addListener(MockitoListener listener) {
+        for (MockitoListener existing : listeners) {
+            if (existing.getClass().equals(listener.getClass())) {
+                Reporter.redundantMockitoListener(listener.getClass().getSimpleName());
+            }
+        }
+        this.listeners.add(listener);
     }
-}
\ No newline at end of file
+
+    public void removeListener(MockitoListener listener) {
+        this.listeners.remove(listener);
+    }
+
+    public void setVerificationStrategy(VerificationStrategy strategy) {
+        this.verificationStrategy = strategy;
+    }
+
+    public VerificationMode maybeVerifyLazily(VerificationMode mode) {
+        return this.verificationStrategy.maybeVerifyLazily(mode);
+    }
+
+    public void clearListeners() {
+        listeners.clear();
+    }
+
+     /*
+
+     //TODO 545 thread safety of all mockito
+
+     use cases:
+        - single threaded execution throughout
+        - single threaded mock creation, stubbing & verification, multi-threaded interaction with mock
+        - thread per test case
+
+     */
+}
diff --git a/src/main/java/org/mockito/internal/progress/SequenceNumber.java b/src/main/java/org/mockito/internal/progress/SequenceNumber.java
index 04cb006..bc7a07d 100644
--- a/src/main/java/org/mockito/internal/progress/SequenceNumber.java
+++ b/src/main/java/org/mockito/internal/progress/SequenceNumber.java
@@ -2,13 +2,13 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.progress;

-

-public class SequenceNumber {

-    

-    private static int sequenceNumber = 1;

-

-    public static synchronized int next() {

-        return sequenceNumber++;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.progress;
+
+public class SequenceNumber {
+
+    private static int sequenceNumber = 1;
+
+    public static synchronized int next() {
+        return sequenceNumber++;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/progress/ThreadSafeMockingProgress.java b/src/main/java/org/mockito/internal/progress/ThreadSafeMockingProgress.java
index 669af6d..4735a11 100644
--- a/src/main/java/org/mockito/internal/progress/ThreadSafeMockingProgress.java
+++ b/src/main/java/org/mockito/internal/progress/ThreadSafeMockingProgress.java
@@ -2,77 +2,31 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-
 package org.mockito.internal.progress;
 
-import org.mockito.internal.listeners.MockingProgressListener;
-import org.mockito.invocation.Invocation;
-import org.mockito.verification.VerificationMode;
+/**
+ * Provides access to the {@link MockingProgress} of a corresponding {@link Thread}. Every {@link Thread} in Mockito has it s own {@link MockingProgress} to avoid data races while stubbing.
+ */
+public class ThreadSafeMockingProgress {
 
-import java.io.Serializable;
-
-@SuppressWarnings("unchecked")
-public class ThreadSafeMockingProgress implements MockingProgress, Serializable {
-    
-    private static final long serialVersionUID = 6839454041642082618L;
-    private static final ThreadLocal<MockingProgress> mockingProgress = new ThreadLocal<MockingProgress>();
-
-    static MockingProgress threadSafely() {
-        if (mockingProgress.get() == null) {
-            mockingProgress.set(new MockingProgressImpl());
+    private static final ThreadLocal<MockingProgress> MOCKING_PROGRESS_PROVIDER = new ThreadLocal<MockingProgress>() {
+        @Override
+        protected MockingProgress initialValue() {
+            return new MockingProgressImpl();
         }
-        return mockingProgress.get();
-    }
-    
-    public void reportOngoingStubbing(IOngoingStubbing iOngoingStubbing) {
-        threadSafely().reportOngoingStubbing(iOngoingStubbing);
+    };
+
+    private ThreadSafeMockingProgress() {
     }
 
-    public IOngoingStubbing pullOngoingStubbing() {
-        return threadSafely().pullOngoingStubbing();
+    /**
+     * Returns the {@link MockingProgress} for the current Thread.
+     * <p>
+     * <b>IMPORTANT</b>: Never assign and access the returned {@link MockingProgress} to an instance or static field. Thread safety can not be guaranteed in this case, cause the Thread that wrote the field might not be the same that read it. In other words multiple threads will access the same {@link MockingProgress}.
+     *
+     * @return never <code>null</code>
+     */
+    public final static MockingProgress mockingProgress() {
+        return MOCKING_PROGRESS_PROVIDER.get();
     }
-    
-    public void verificationStarted(VerificationMode verify) {
-        threadSafely().verificationStarted(verify);
-    }
-
-    public VerificationMode pullVerificationMode() {
-        return threadSafely().pullVerificationMode();
-    }
-
-    public void stubbingStarted() {
-        threadSafely().stubbingStarted();
-    }
-
-    public void validateState() {
-        threadSafely().validateState();
-    }
-
-    public void stubbingCompleted(Invocation invocation) {
-        threadSafely().stubbingCompleted(invocation);
-    }
-    
-    public String toString() {
-        return threadSafely().toString();
-    }
-
-    public void reset() {
-        threadSafely().reset();
-    }
-
-    public void resetOngoingStubbing() {
-        threadSafely().resetOngoingStubbing();
-    }
-
-    public ArgumentMatcherStorage getArgumentMatcherStorage() {
-        return threadSafely().getArgumentMatcherStorage();
-    }
-    
-    public void mockingStarted(Object mock, Class classToMock) {
-        threadSafely().mockingStarted(mock, classToMock);
-    }
-
-    public void setListener(MockingProgressListener listener) {
-        threadSafely().setListener(listener);
-    }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/progress/package-info.java b/src/main/java/org/mockito/internal/progress/package-info.java
new file mode 100644
index 0000000..8b0c51c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/progress/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mocking progress stateful classes.
+ */
+package org.mockito.internal.progress;
diff --git a/src/main/java/org/mockito/internal/progress/package.html b/src/main/java/org/mockito/internal/progress/package.html
deleted file mode 100644
index 0db3625..0000000
--- a/src/main/java/org/mockito/internal/progress/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Mocking progress stateful classes. 
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/reporting/Discrepancy.java b/src/main/java/org/mockito/internal/reporting/Discrepancy.java
index 420bc5a..655af9d 100644
--- a/src/main/java/org/mockito/internal/reporting/Discrepancy.java
+++ b/src/main/java/org/mockito/internal/reporting/Discrepancy.java
@@ -2,31 +2,31 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.reporting;

-

-public class Discrepancy {

-

-    private final int wantedCount;

-    private final int actualCount;

-

-    public Discrepancy(int wantedCount, int actualCount) {

-        this.wantedCount = wantedCount;

-        this.actualCount = actualCount;

-    }

-

-    public int getWantedCount() {

-        return wantedCount;

-    }

-    

-    public String getPluralizedWantedCount() {

-        return Pluralizer.pluralize(wantedCount);

-    }

-

-    public int getActualCount() {

-        return actualCount;

-    }

-

-    public String getPluralizedActualCount() {

-        return Pluralizer.pluralize(actualCount);

-    }

-}
\ No newline at end of file
+package org.mockito.internal.reporting;
+
+public class Discrepancy {
+
+    private final int wantedCount;
+    private final int actualCount;
+
+    public Discrepancy(int wantedCount, int actualCount) {
+        this.wantedCount = wantedCount;
+        this.actualCount = actualCount;
+    }
+
+    public int getWantedCount() {
+        return wantedCount;
+    }
+
+    public String getPluralizedWantedCount() {
+        return Pluralizer.pluralize(wantedCount);
+    }
+
+    public int getActualCount() {
+        return actualCount;
+    }
+
+    public String getPluralizedActualCount() {
+        return Pluralizer.pluralize(actualCount);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/reporting/Pluralizer.java b/src/main/java/org/mockito/internal/reporting/Pluralizer.java
index 57f336a..1e8d0e3 100644
--- a/src/main/java/org/mockito/internal/reporting/Pluralizer.java
+++ b/src/main/java/org/mockito/internal/reporting/Pluralizer.java
@@ -2,11 +2,19 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.reporting;

-

-public class Pluralizer {

-

-    public static String pluralize(int number) {

-        return number == 1 ? "1 time" : number + " times";

-    }

-}

+package org.mockito.internal.reporting;
+
+public class Pluralizer {
+
+    public static String pluralize(int number) {
+        return number == 1 ? "1 time" : number + " times";
+    }
+
+    public static String were_exactly_x_interactions(int x) {
+        if (x == 1) {
+            return "was exactly 1 interaction";
+        } else {
+            return "were exactly " + x + " interactions";
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/reporting/PrintSettings.java b/src/main/java/org/mockito/internal/reporting/PrintSettings.java
index 63e1c6c..e70f953 100644
--- a/src/main/java/org/mockito/internal/reporting/PrintSettings.java
+++ b/src/main/java/org/mockito/internal/reporting/PrintSettings.java
@@ -2,63 +2,64 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.reporting;

-

-import org.hamcrest.Matcher;

-import org.mockito.internal.invocation.ArgumentsProcessor;

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.internal.matchers.MatchersPrinter;

-import org.mockito.internal.util.MockUtil;

-import org.mockito.invocation.Invocation;

-

-import java.util.Arrays;

-import java.util.LinkedList;

-import java.util.List;

-

-public class PrintSettings {

-

-    public static final int MAX_LINE_LENGTH = 45;

-    private boolean multiline;

-    private List<Integer> withTypeInfo = new LinkedList<Integer>();

-

-    public void setMultiline(boolean multiline) {

-        this.multiline = multiline;

-    }

-

-    public boolean isMultiline() {

-        return multiline;

-    }

-

-    public static PrintSettings verboseMatchers(Integer ... indexesOfMatchers) {

-        PrintSettings settings = new PrintSettings();

-        settings.setMatchersToBeDescribedWithExtraTypeInfo(indexesOfMatchers);

-        return settings;

-    }

-

-    public boolean extraTypeInfoFor(int argumentIndex) {

-        return withTypeInfo.contains(argumentIndex);

-    }

-

-    public void setMatchersToBeDescribedWithExtraTypeInfo(Integer[] indexesOfMatchers) {

-        this.withTypeInfo = Arrays.asList(indexesOfMatchers);

-    }

-

-    public String print(List<Matcher> matchers, Invocation invocation) {

-        MatchersPrinter matchersPrinter = new MatchersPrinter();

-        String qualifiedName = new MockUtil().getMockName(invocation.getMock()) + "." + invocation.getMethod().getName();

-        String invocationString = qualifiedName + matchersPrinter.getArgumentsLine(matchers, this);

-        if (isMultiline() || (!matchers.isEmpty() && invocationString.length() > MAX_LINE_LENGTH)) {

-            return qualifiedName + matchersPrinter.getArgumentsBlock(matchers, this);

-        } else {

-            return invocationString;

-        }

-    }

-

-    public String print(Invocation invocation) {

-        return print(ArgumentsProcessor.argumentsToMatchers(invocation.getArguments()), invocation);

-    }

-

-    public String print(InvocationMatcher invocationMatcher) {

-        return print(invocationMatcher.getMatchers(), invocationMatcher.getInvocation());

-    }

-}
\ No newline at end of file
+package org.mockito.internal.reporting;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.invocation.ArgumentsProcessor;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.matchers.text.MatchersPrinter;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+public class PrintSettings {
+
+    public static final int MAX_LINE_LENGTH = 45;
+    private boolean multiline;
+    private List<Integer> withTypeInfo = new LinkedList<Integer>();
+
+    public void setMultiline(boolean multiline) {
+        this.multiline = multiline;
+    }
+
+    public boolean isMultiline() {
+        return multiline;
+    }
+
+    public static PrintSettings verboseMatchers(Integer ... indexesOfMatchers) {
+        PrintSettings settings = new PrintSettings();
+        settings.setMatchersToBeDescribedWithExtraTypeInfo(indexesOfMatchers);
+        return settings;
+    }
+
+    public boolean extraTypeInfoFor(int argumentIndex) {
+        return withTypeInfo.contains(argumentIndex);
+    }
+
+    public void setMatchersToBeDescribedWithExtraTypeInfo(Integer[] indexesOfMatchers) {
+        this.withTypeInfo = Arrays.asList(indexesOfMatchers);
+    }
+
+    public String print(List<ArgumentMatcher> matchers, Invocation invocation) {
+        MatchersPrinter matchersPrinter = new MatchersPrinter();
+        String qualifiedName = MockUtil.getMockName(invocation.getMock()) + "." + invocation.getMethod().getName();
+        String invocationString = qualifiedName + matchersPrinter.getArgumentsLine(matchers, this);
+        if (isMultiline() || (!matchers.isEmpty() && invocationString.length() > MAX_LINE_LENGTH)) {
+            return qualifiedName + matchersPrinter.getArgumentsBlock(matchers, this);
+        } else {
+            return invocationString;
+        }
+    }
+
+    public String print(Invocation invocation) {
+        return print(ArgumentsProcessor.argumentsToMatchers(invocation.getArguments()), invocation);
+    }
+
+    public String print(MatchableInvocation invocation) {
+        return print(invocation.getMatchers(), invocation.getInvocation());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/reporting/SmartPrinter.java b/src/main/java/org/mockito/internal/reporting/SmartPrinter.java
index c59492c..89535d2 100644
--- a/src/main/java/org/mockito/internal/reporting/SmartPrinter.java
+++ b/src/main/java/org/mockito/internal/reporting/SmartPrinter.java
@@ -2,36 +2,37 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.reporting;

-

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.Invocation;

-

-/**

- * Makes sure both wanted and actual are printed consistently (single line or multiline)

- * <p>

- * Makes arguments printed with types if necessary

- */

-public class SmartPrinter {

-

-    private final String wanted;

-    private final String actual;

-

-    public SmartPrinter(InvocationMatcher wanted, Invocation actual, Integer ... indexesOfMatchersToBeDescribedWithExtraTypeInfo) {

-        PrintSettings printSettings = new PrintSettings();

-        printSettings.setMultiline(wanted.toString().contains("\n") || actual.toString().contains("\n"));

-        printSettings.setMatchersToBeDescribedWithExtraTypeInfo(indexesOfMatchersToBeDescribedWithExtraTypeInfo);

-        

-        this.wanted = printSettings.print(wanted);

-        this.actual = printSettings.print(actual);

-    }

-

-    public String getWanted() {

-        return wanted;

-    }

-

-    public String getActual() {

-        return actual;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.reporting;
+
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+/**
+ * Makes sure both wanted and actual are printed consistently (single line or multiline)
+ * <p>
+ * Makes arguments printed with types if necessary
+ */
+public class SmartPrinter {
+
+    private final String wanted;
+    private final String actual;
+
+    public SmartPrinter(MatchableInvocation wanted, Invocation actual, Integer ... indexesOfMatchersToBeDescribedWithExtraTypeInfo) {
+        PrintSettings printSettings = new PrintSettings();
+        printSettings.setMultiline(wanted.toString().contains("\n") || actual.toString().contains("\n"));
+        printSettings.setMatchersToBeDescribedWithExtraTypeInfo(indexesOfMatchersToBeDescribedWithExtraTypeInfo);
+
+        this.wanted = printSettings.print(wanted);
+        this.actual = printSettings.print(actual);
+    }
+
+    public String getWanted() {
+        return wanted;
+    }
+
+    public String getActual() {
+        return actual;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/reporting/package-info.java b/src/main/java/org/mockito/internal/reporting/package-info.java
new file mode 100644
index 0000000..acb00ef
--- /dev/null
+++ b/src/main/java/org/mockito/internal/reporting/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Deals with nicely printing verification errors.
+ */
+package org.mockito.internal.reporting;
diff --git a/src/main/java/org/mockito/internal/reporting/package.html b/src/main/java/org/mockito/internal/reporting/package.html
deleted file mode 100644
index 92b9096..0000000
--- a/src/main/java/org/mockito/internal/reporting/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Deals with nicely printing verification errors 
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/runners/DefaultInternalRunner.java b/src/main/java/org/mockito/internal/runners/DefaultInternalRunner.java
new file mode 100644
index 0000000..c415736
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/DefaultInternalRunner.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.junit.MockitoTestListener;
+import org.mockito.internal.util.Supplier;
+
+public class DefaultInternalRunner implements InternalRunner {
+
+    private final BlockJUnit4ClassRunner runner;
+
+    public DefaultInternalRunner(Class<?> testClass, final Supplier<MockitoTestListener> listenerSupplier) throws InitializationError {
+        runner = new BlockJUnit4ClassRunner(testClass) {
+
+            public Object target;
+            private MockitoTestListener mockitoTestListener;
+
+            protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
+                // get new test listener and add add it to the framework
+                mockitoTestListener = listenerSupplier.get();
+                Mockito.framework().addListener(mockitoTestListener);
+
+                // init annotated mocks before tests
+                MockitoAnnotations.initMocks(target);
+                this.target = target;
+                return super.withBefores(method, target, statement);
+            }
+
+            public void run(final RunNotifier notifier) {
+                RunListener listener = new RunListener() {
+                    Throwable failure;
+
+                    public void testFailure(Failure failure) throws Exception {
+                        this.failure = failure.getException();
+                    }
+
+                    public void testFinished(Description description) throws Exception {
+                        super.testFinished(description);
+                        try {
+                            if (mockitoTestListener != null) {
+                                Mockito.framework().removeListener(mockitoTestListener);
+                                mockitoTestListener.testFinished(new DefaultTestFinishedEvent(target, description.getMethodName(), failure));
+                            }
+                            Mockito.validateMockitoUsage();
+                        } catch(Throwable t) {
+                            //In order to produce clean exception to the user we need to fire test failure with the right description
+                            //Otherwise JUnit framework will report failure with some generic test name
+                            notifier.fireTestFailure(new Failure(description, t));
+                        }
+                    }
+                };
+
+                notifier.addListener(listener);
+                super.run(notifier);
+            }
+        };
+    }
+
+    public void run(final RunNotifier notifier) {
+        runner.run(notifier);
+    }
+
+    public Description getDescription() {
+        return runner.getDescription();
+    }
+
+    public void filter(Filter filter) throws NoTestsRemainException {
+        runner.filter(filter);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/DefaultTestFinishedEvent.java b/src/main/java/org/mockito/internal/runners/DefaultTestFinishedEvent.java
new file mode 100644
index 0000000..d1a5e93
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/DefaultTestFinishedEvent.java
@@ -0,0 +1,31 @@
+package org.mockito.internal.runners;
+
+import org.mockito.internal.junit.TestFinishedEvent;
+
+class DefaultTestFinishedEvent implements TestFinishedEvent {
+
+    private final Object testClassInstance;
+    private final String testMethodName;
+    private final Throwable failure;
+
+    DefaultTestFinishedEvent(Object testClassInstance, String testMethodName, Throwable failure) {
+        this.testClassInstance = testClassInstance;
+        this.testMethodName = testMethodName;
+        this.failure = failure;
+    }
+
+    @Override
+    public Object getTestClassInstance() {
+        return testClassInstance;
+    }
+
+    @Override
+    public String getTestMethodName() {
+        return testMethodName;
+    }
+
+    @Override
+    public Throwable getFailure() {
+        return failure;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/InternalRunner.java b/src/main/java/org/mockito/internal/runners/InternalRunner.java
new file mode 100644
index 0000000..85b2f3c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/InternalRunner.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.notification.RunNotifier;
+
+/**
+ * I'm using this surrogate interface to hide internal Runner implementations.
+ * Surrogate cannot be used with &#064;RunWith therefore it is less likely clients will use interal runners.
+ */
+public interface InternalRunner extends Filterable {
+
+    void run(RunNotifier notifier);
+
+    Description getDescription();
+
+}
diff --git a/src/main/java/org/mockito/internal/runners/JUnit44RunnerImpl.java b/src/main/java/org/mockito/internal/runners/JUnit44RunnerImpl.java
deleted file mode 100644
index 2180a97..0000000
--- a/src/main/java/org/mockito/internal/runners/JUnit44RunnerImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.runners;
-
-import org.junit.internal.runners.InitializationError;
-import org.junit.internal.runners.JUnit4ClassRunner;
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.notification.RunNotifier;
-import org.mockito.MockitoAnnotations;
-import org.mockito.internal.runners.util.FrameworkUsageValidator;
-
-@SuppressWarnings("deprecation")
-public class JUnit44RunnerImpl implements RunnerImpl {
-
-	JUnit4ClassRunner runner;
-
-    public JUnit44RunnerImpl(Class<?> klass) throws InitializationError {
-        this.runner = new JUnit4ClassRunner(klass) {
-            @Override
-            protected Object createTest() throws Exception {
-                Object test = super.createTest();
-                MockitoAnnotations.initMocks(test);
-                return test;
-            }
-        };
-    }
-
-    public void run(RunNotifier notifier) {
-        // add listener that validates framework usage at the end of each test
-        notifier.addListener(new FrameworkUsageValidator(notifier));
-
-        runner.run(notifier);
-    }
-
-    public Description getDescription() {
-        return runner.getDescription();
-    }
-
-	public void filter(Filter filter) throws NoTestsRemainException {
-		runner.filter(filter);
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/runners/JUnit45AndHigherRunnerImpl.java b/src/main/java/org/mockito/internal/runners/JUnit45AndHigherRunnerImpl.java
deleted file mode 100644
index d7c6ada..0000000
--- a/src/main/java/org/mockito/internal/runners/JUnit45AndHigherRunnerImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.runners;

-

-import org.junit.runner.Description;

-import org.junit.runner.manipulation.Filter;

-import org.junit.runner.manipulation.NoTestsRemainException;

-import org.junit.runner.notification.RunNotifier;

-import org.junit.runners.BlockJUnit4ClassRunner;

-import org.junit.runners.model.FrameworkMethod;

-import org.junit.runners.model.InitializationError;

-import org.junit.runners.model.Statement;

-import org.mockito.MockitoAnnotations;

-import org.mockito.internal.runners.util.FrameworkUsageValidator;

-

-public class JUnit45AndHigherRunnerImpl implements RunnerImpl {

-

-    private final BlockJUnit4ClassRunner runner;

-

-    public JUnit45AndHigherRunnerImpl(Class<?> klass) throws InitializationError {

-        runner = new BlockJUnit4ClassRunner(klass) {

-            protected Statement withBefores(FrameworkMethod method, Object target,

-                    Statement statement) {

-                // init annotated mocks before tests

-                MockitoAnnotations.initMocks(target);

-                return super.withBefores(method, target, statement);

-            }

-        };

-    }

-

-    public void run(final RunNotifier notifier) {

-        // add listener that validates framework usage at the end of each test

-        notifier.addListener(new FrameworkUsageValidator(notifier));

-

-        runner.run(notifier);

-    }

-

-    public Description getDescription() {

-        return runner.getDescription();

-    }

-

-	public void filter(Filter filter) throws NoTestsRemainException {

-		runner.filter(filter);

-	}

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/runners/RunnerFactory.java b/src/main/java/org/mockito/internal/runners/RunnerFactory.java
index 871e607..61456dc 100644
--- a/src/main/java/org/mockito/internal/runners/RunnerFactory.java
+++ b/src/main/java/org/mockito/internal/runners/RunnerFactory.java
@@ -2,52 +2,91 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.runners;

-

-import org.mockito.exceptions.base.MockitoException;

-import org.mockito.internal.runners.util.RunnerProvider;

-import org.mockito.internal.runners.util.TestMethodsFinder;

-

-import java.lang.reflect.InvocationTargetException;

-

-public class RunnerFactory {

-

-    private final RunnerProvider runnerProvider;

-

-    RunnerFactory(RunnerProvider runnerProvider) {

-        this.runnerProvider = runnerProvider;

-    }

-

-    public RunnerFactory() {

-        this(new RunnerProvider());

-    }

-

-    public RunnerImpl create(Class<?> klass) throws InvocationTargetException {

-        try {

-            if (runnerProvider.isJUnit45OrHigherAvailable()) {

-                return runnerProvider.newInstance("org.mockito.internal.runners.JUnit45AndHigherRunnerImpl", klass);

-            } else {

-                return runnerProvider.newInstance("org.mockito.internal.runners.JUnit44RunnerImpl", klass);

-            }

-        } catch (InvocationTargetException e) {

-            if (!new TestMethodsFinder().hasTestMethods(klass)) {

-                throw new MockitoException(

-                    "\n" +

-                    "\n" +

-                    "No tests found in " + klass.getSimpleName() + "\n" +

-                    "Haven't you forgot @Test annotation?\n"

-                    , e);

-            }

-            throw e;

-        } catch (Throwable t) {

-            throw new MockitoException(

-                    "\n" +

-                    "\n" +

-                    "MockitoRunner can only be used with JUnit 4.4 or higher.\n" +

-                    "You can upgrade your JUnit version or write your own Runner (please consider contributing your runner to the Mockito community).\n" +

-                    "Bear in mind that you can still enjoy all features of the framework without using runners (they are completely optional).\n" +

-                    "If you get this error despite using JUnit 4.4 or higher then please report this error to the mockito mailing list.\n"

-                    , t);

-        }

-    }

-}
\ No newline at end of file
+package org.mockito.internal.runners;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.junit.MismatchReportingTestListener;
+import org.mockito.internal.junit.MockitoTestListener;
+import org.mockito.internal.junit.NoOpTestListener;
+import org.mockito.internal.junit.StrictStubsRunnerTestListener;
+import org.mockito.internal.runners.util.RunnerProvider;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+import org.mockito.internal.util.Supplier;
+
+import java.lang.reflect.InvocationTargetException;
+
+import static org.mockito.internal.runners.util.TestMethodsFinder.hasTestMethods;
+
+/**
+ * Creates instances of Mockito JUnit Runner in a safe way, e.g. detecting inadequate version of JUnit, etc.
+ */
+public class RunnerFactory {
+
+    /**
+     * Creates silent runner implementation
+     */
+    public InternalRunner create(Class<?> klass) throws InvocationTargetException {
+        return create(klass, new Supplier<MockitoTestListener>() {
+            public MockitoTestListener get() {
+                return new NoOpTestListener();
+            }
+        });
+    }
+
+    /**
+     * Creates strict runner implementation
+     */
+    public InternalRunner createStrict(Class<?> klass) throws InvocationTargetException {
+        return create(klass, new Supplier<MockitoTestListener>() {
+            public MockitoTestListener get() {
+                return new MismatchReportingTestListener(new ConsoleMockitoLogger());
+            }
+        });
+    }
+
+    /**
+     * Creates strict stubs runner implementation
+     *
+     * TODO, let's try to apply Brice suggestion and use switch + Strictness
+     */
+    public InternalRunner createStrictStubs(Class<?> klass) throws InvocationTargetException {
+        return create(klass, new Supplier<MockitoTestListener>() {
+            public MockitoTestListener get() {
+                return new StrictStubsRunnerTestListener();
+            }
+        });
+    }
+
+    /**
+     * Creates runner implementation with provided listener supplier
+     */
+    public InternalRunner create(Class<?> klass, Supplier<MockitoTestListener> listenerSupplier) throws InvocationTargetException {
+        try {
+            String runnerClassName = "org.mockito.internal.runners.DefaultInternalRunner";
+            //Warning: I'm using String literal on purpose!
+            //When JUnit is not on classpath, we want the code to throw exception here so that we can catch it
+            //If we statically link the class, we will get Error when class is loaded
+            return new RunnerProvider().newInstance(runnerClassName, klass, listenerSupplier);
+        } catch (InvocationTargetException e) {
+            if (!hasTestMethods(klass)) {
+                throw new MockitoException(
+                    "\n" +
+                    "\n" +
+                    "No tests found in " + klass.getSimpleName() + "\n" +
+                    "Is the method annotated with @Test?\n" +
+                    "Is the method public?\n"
+                    , e);
+            }
+            throw e;
+        } catch (Throwable t) {
+            throw new MockitoException(
+                    "\n" +
+                    "\n" +
+                    "MockitoRunner can only be used with JUnit 4.5 or higher.\n" +
+                    "You can upgrade your JUnit version or write your own Runner (please consider contributing your runner to the Mockito community).\n" +
+                    "Bear in mind that you can still enjoy all features of the framework without using runners (they are completely optional).\n" +
+                    "If you get this error despite using JUnit 4.5 or higher then please report this error to the mockito mailing list.\n"
+                    , t);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/RunnerImpl.java b/src/main/java/org/mockito/internal/runners/RunnerImpl.java
deleted file mode 100644
index a723b88..0000000
--- a/src/main/java/org/mockito/internal/runners/RunnerImpl.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.runners;

-

-import org.junit.runner.Description;

-import org.junit.runner.manipulation.Filterable;

-import org.junit.runner.notification.RunNotifier;

-

-/**

- * I'm using this surrogate interface to hide internal Runner implementations.

- * Surrogate cannot be used with &#064;RunWith therefore it is less likely clients will use interal runners.

- */

-public interface RunnerImpl extends Filterable{

-

-    void run(RunNotifier notifier);

-

-    Description getDescription();

-    

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/runners/StrictRunner.java b/src/main/java/org/mockito/internal/runners/StrictRunner.java
new file mode 100644
index 0000000..d87289f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/StrictRunner.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.Mockito;
+import org.mockito.internal.junit.UnnecessaryStubbingsReporter;
+import org.mockito.internal.runners.util.FailureDetector;
+
+public class StrictRunner implements InternalRunner {
+
+    private final Class<?> testClass;
+    private final InternalRunner runner;
+    private boolean filterRequested;
+
+    /**
+     * @param runner - the runner to wrap around
+     * @param testClass - for reporting purposes
+     */
+    public StrictRunner(InternalRunner runner, Class<?> testClass) {
+        this.runner = runner;
+        this.testClass = testClass;
+    }
+
+    public void run(RunNotifier notifier) {
+        //TODO need to be able to opt in for full stack trace instead of just relying on the stack trace filter
+        UnnecessaryStubbingsReporter reporter = new UnnecessaryStubbingsReporter();
+        FailureDetector listener = new FailureDetector();
+
+        Mockito.framework().addListener(reporter);
+        try {
+            // add listener that detects test failures
+            notifier.addListener(listener);
+            runner.run(notifier);
+        } finally {
+            Mockito.framework().removeListener(reporter);
+        }
+
+        if (!filterRequested && listener.isSuccessful()) {
+            //only report when:
+            //1. if all tests from given test have ran (filter requested is false)
+            //   Otherwise we would report unnecessary stubs even if the user runs just single test from the class
+            //2. tests are successful (we don't want to add an extra failure on top of any existing failure, to avoid confusion)
+            reporter.validateUnusedStubs(testClass, notifier);
+        }
+    }
+
+    public Description getDescription() {
+        return runner.getDescription();
+    }
+
+    public void filter(Filter filter) throws NoTestsRemainException {
+        filterRequested = true;
+        runner.filter(filter);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/package-info.java b/src/main/java/org/mockito/internal/runners/package-info.java
new file mode 100644
index 0000000..07e001f
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Internal classes for runners implementations.
+ */
+package org.mockito.internal.runners;
diff --git a/src/main/java/org/mockito/internal/runners/package.html b/src/main/java/org/mockito/internal/runners/package.html
deleted file mode 100644
index 6a1b89e..0000000
--- a/src/main/java/org/mockito/internal/runners/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Internal classes for runners implementations
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/runners/util/FailureDetector.java b/src/main/java/org/mockito/internal/runners/util/FailureDetector.java
new file mode 100644
index 0000000..14d4eba
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/util/FailureDetector.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners.util;
+
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * Implementation of JUnit run listener that knows when any of the tests failed
+ */
+public class FailureDetector extends RunListener {
+
+    private boolean failed;
+
+    @Override
+    public void testFailure(Failure failure) throws Exception {
+        super.testFailure(failure);
+        failed = true;
+    }
+
+    public boolean isSuccessful() {
+        return !failed;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/util/FrameworkUsageValidator.java b/src/main/java/org/mockito/internal/runners/util/FrameworkUsageValidator.java
deleted file mode 100644
index 64edc48..0000000
--- a/src/main/java/org/mockito/internal/runners/util/FrameworkUsageValidator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.runners.util;

-

-import org.junit.runner.Description;

-import org.junit.runner.notification.Failure;

-import org.junit.runner.notification.RunListener;

-import org.junit.runner.notification.RunNotifier;

-import org.mockito.Mockito;

-

-public class FrameworkUsageValidator extends RunListener {

-    

-    private final RunNotifier notifier;

-

-    public FrameworkUsageValidator(RunNotifier notifier) {

-        this.notifier = notifier;

-    }

-

-    @Override

-    public void testFinished(Description description) throws Exception {

-        super.testFinished(description);

-        try {

-            Mockito.validateMockitoUsage();

-        } catch(Throwable t) {

-            notifier.fireTestFailure(new Failure(description, t));

-        }

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/runners/util/RunnerProvider.java b/src/main/java/org/mockito/internal/runners/util/RunnerProvider.java
index 8ae12d7..e3ed92a 100644
--- a/src/main/java/org/mockito/internal/runners/util/RunnerProvider.java
+++ b/src/main/java/org/mockito/internal/runners/util/RunnerProvider.java
@@ -2,45 +2,33 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.runners.util;

-

-import java.lang.reflect.Constructor;

-import java.lang.reflect.InvocationTargetException;

-

-import org.mockito.internal.runners.RunnerImpl;

-

-public class RunnerProvider {

-

-    private static boolean hasJUnit45OrHigher; 

-

-    static {

-        try {

-            Class.forName("org.junit.runners.BlockJUnit4ClassRunner");

-            hasJUnit45OrHigher = true;

-        } catch (Throwable t) {

-            hasJUnit45OrHigher = false;

-        }

-    }

-    

-    public boolean isJUnit45OrHigherAvailable() {

-        return hasJUnit45OrHigher;

-    }

-

-    public RunnerImpl newInstance(String runnerClassName, Class<?> constructorParam) throws Exception {

-        Constructor<?> constructor;

-        try {

-            Class<?> runnerClass = Class.forName(runnerClassName);

-            constructor = runnerClass.getConstructor(Class.class.getClass());

-        } catch (Exception e) {

-            throw new RuntimeException(e);

-        }

-        

-        try {

-            return (RunnerImpl) constructor.newInstance(constructorParam);

-        } catch (InvocationTargetException e) {

-            throw e;

-        } catch (Exception e) {

-            throw new RuntimeException(e);        

-        }

-    }

-}
\ No newline at end of file
+package org.mockito.internal.runners.util;
+
+import org.mockito.internal.runners.InternalRunner;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+public class RunnerProvider {
+
+    public InternalRunner newInstance(String runnerClassName, Object ... constructorArgs) throws Exception {
+        Constructor<?> constructor;
+        try {
+            Class<?> runnerClass = Class.forName(runnerClassName);
+            if (runnerClass.getConstructors().length != 1) {
+                throw new IllegalArgumentException("Expected " + runnerClassName + " to have exactly one constructor.");
+            }
+            constructor = runnerClass.getConstructors()[0];
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        try {
+            return (InternalRunner) constructor.newInstance(constructorArgs);
+        } catch (InvocationTargetException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/util/TestMethodsFinder.java b/src/main/java/org/mockito/internal/runners/util/TestMethodsFinder.java
index 3becfe2..f435df3 100644
--- a/src/main/java/org/mockito/internal/runners/util/TestMethodsFinder.java
+++ b/src/main/java/org/mockito/internal/runners/util/TestMethodsFinder.java
@@ -2,20 +2,23 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.runners.util;

-

-import org.junit.Test;

-

-import java.lang.reflect.Method;

-

-public class TestMethodsFinder {

-    public boolean hasTestMethods(Class<?> klass) {

-        Method[] methods = klass.getMethods();

-        for(Method m:methods) {

-            if (m.isAnnotationPresent(Test.class)) {

-                return true;

-            }

-        }

-        return false;

-    }

-}

+package org.mockito.internal.runners.util;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class TestMethodsFinder {
+
+    private TestMethodsFinder() {}
+
+    public static boolean hasTestMethods(Class<?> klass) {
+        Method[] methods = klass.getMethods();
+        for(Method m:methods) {
+            if (m.isAnnotationPresent(Test.class)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/runners/util/package-info.java b/src/main/java/org/mockito/internal/runners/util/package-info.java
new file mode 100644
index 0000000..4c11616
--- /dev/null
+++ b/src/main/java/org/mockito/internal/runners/util/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Internal utils for runner implementations.
+ */
+package org.mockito.internal.runners.util;
diff --git a/src/main/java/org/mockito/internal/runners/util/package.html b/src/main/java/org/mockito/internal/runners/util/package.html
deleted file mode 100644
index b6c4110..0000000
--- a/src/main/java/org/mockito/internal/runners/util/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Internal utils for runner implementations
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/session/DefaultMockitoSessionBuilder.java b/src/main/java/org/mockito/internal/session/DefaultMockitoSessionBuilder.java
new file mode 100644
index 0000000..762b69c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/session/DefaultMockitoSessionBuilder.java
@@ -0,0 +1,33 @@
+package org.mockito.internal.session;
+
+import org.mockito.MockitoSession;
+import org.mockito.internal.framework.DefaultMockitoSession;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+import org.mockito.quality.Strictness;
+import org.mockito.session.MockitoSessionBuilder;
+
+public class DefaultMockitoSessionBuilder implements MockitoSessionBuilder {
+
+    private Object testClassInstance;
+    private Strictness strictness;
+
+    @Override
+    public MockitoSessionBuilder initMocks(Object testClassInstance) {
+        this.testClassInstance = testClassInstance;
+        return this;
+    }
+
+    @Override
+    public MockitoSessionBuilder strictness(Strictness strictness) {
+        this.strictness = strictness;
+        return this;
+    }
+
+    @Override
+    public MockitoSession startMocking() {
+        //Configure default values
+        Object effectiveTest = this.testClassInstance == null ? new Object() : this.testClassInstance;
+        Strictness effectiveStrictness = this.strictness == null ? Strictness.STRICT_STUBS : this.strictness;
+        return new DefaultMockitoSession(effectiveTest, effectiveStrictness, new ConsoleMockitoLogger());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java b/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java
index 80270fa..c55c82b 100644
--- a/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java
+++ b/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java
@@ -1,82 +1,70 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing;

-

-import org.mockito.internal.stubbing.answers.CallsRealMethods;

-import org.mockito.internal.stubbing.answers.Returns;

-import org.mockito.internal.stubbing.answers.ThrowsException;

-import org.mockito.internal.stubbing.answers.ThrowsExceptionClass;

-import org.mockito.stubbing.DeprecatedOngoingStubbing;

-import org.mockito.stubbing.OngoingStubbing;

-

-public abstract class BaseStubbing<T> implements OngoingStubbing<T>, DeprecatedOngoingStubbing<T> {

-

-    //TODO why we need this method? The other thenReturn covers it.

-    public OngoingStubbing<T> thenReturn(T value) {

-        return thenAnswer(new Returns(value));

-    }

-

-    public OngoingStubbing<T> thenReturn(T value, T... values) {

-        OngoingStubbing<T> stubbing = thenReturn(value);            

-        if (values == null) {

-            //TODO below does not seem right

-            return stubbing.thenReturn(null);

-        }

-        for (T v: values) {

-            stubbing = stubbing.thenReturn(v);

-        }

-        return stubbing;

-    }

-

-    private OngoingStubbing<T> thenThrow(Throwable throwable) {

-        return thenAnswer(new ThrowsException(throwable));

-    }

-

-    public OngoingStubbing<T> thenThrow(Throwable... throwables) {

-        if (throwables == null) {

-            thenThrow((Throwable) null);

-        }

-        OngoingStubbing<T> stubbing = null;

-        for (Throwable t: throwables) {

-            if (stubbing == null) {

-                stubbing = thenThrow(t);                    

-            } else {

-                stubbing = stubbing.thenThrow(t);

-            }

-        }

-        return stubbing;

-    }        

-

-    private OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableClass) {

-        return thenAnswer(new ThrowsExceptionClass(throwableClass));

-    }

-

-    public OngoingStubbing<T> thenThrow(Class<? extends Throwable>... throwableClasses) {

-        if (throwableClasses == null) {

-            thenThrow((Throwable) null);

-        }

-        OngoingStubbing<T> stubbing = null;

-        for (Class<? extends Throwable> t: throwableClasses) {

-            if (stubbing == null) {

-                stubbing = thenThrow(t);

-            } else {

-                stubbing = stubbing.thenThrow(t);

-            }

-        }

-        return stubbing;

-    }

-

-    public OngoingStubbing<T> thenCallRealMethod() {

-        return thenAnswer(new CallsRealMethods());

-    }

-

-    public DeprecatedOngoingStubbing<T> toReturn(T value) {

-        return toAnswer(new Returns(value));

-    }

-

-    public DeprecatedOngoingStubbing<T> toThrow(Throwable throwable) {

-        return toAnswer(new ThrowsException(throwable));

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.internal.stubbing.answers.ThrowsExceptionClass;
+import org.mockito.stubbing.OngoingStubbing;
+
+public abstract class BaseStubbing<T> implements OngoingStubbing<T> {
+
+    public OngoingStubbing<T> thenReturn(T value) {
+        return thenAnswer(new Returns(value));
+    }
+
+    @SuppressWarnings({"unchecked","vararg"})
+    public OngoingStubbing<T> thenReturn(T value, T... values) {
+        OngoingStubbing<T> stubbing = thenReturn(value);
+        if (values == null) {
+            //TODO below does not seem right
+            return stubbing.thenReturn(null);
+        }
+        for (T v: values) {
+            stubbing = stubbing.thenReturn(v);
+        }
+        return stubbing;
+    }
+
+    private OngoingStubbing<T> thenThrow(Throwable throwable) {
+        return thenAnswer(new ThrowsException(throwable));
+    }
+
+    public OngoingStubbing<T> thenThrow(Throwable... throwables) {
+        if (throwables == null) {
+            return thenThrow((Throwable) null);
+        }
+        OngoingStubbing<T> stubbing = null;
+        for (Throwable t: throwables) {
+            if (stubbing == null) {
+                stubbing = thenThrow(t);
+            } else {
+                stubbing = stubbing.thenThrow(t);
+            }
+        }
+        return stubbing;
+    }
+
+    public OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableType) {
+        return thenAnswer(new ThrowsExceptionClass(throwableType));
+    }
+
+    @SuppressWarnings ({"unchecked", "varargs"})
+    public OngoingStubbing<T> thenThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown) {
+        if (nextToBeThrown == null) {
+            thenThrow((Throwable) null);
+        }
+        OngoingStubbing<T> stubbing = thenThrow(toBeThrown);
+        for (Class<? extends Throwable> t: nextToBeThrown) {
+            stubbing = stubbing.thenThrow(t);
+        }
+        return stubbing;
+    }
+
+    public OngoingStubbing<T> thenCallRealMethod() {
+        return thenAnswer(new CallsRealMethods());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/ConsecutiveStubbing.java b/src/main/java/org/mockito/internal/stubbing/ConsecutiveStubbing.java
index 2541f63..a5cdc04 100644
--- a/src/main/java/org/mockito/internal/stubbing/ConsecutiveStubbing.java
+++ b/src/main/java/org/mockito/internal/stubbing/ConsecutiveStubbing.java
@@ -2,34 +2,29 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing;

-

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.DeprecatedOngoingStubbing;

-import org.mockito.stubbing.OngoingStubbing;

-

-public class ConsecutiveStubbing<T> extends BaseStubbing<T> {

-    private final InvocationContainerImpl invocationContainerImpl;

-

-    public ConsecutiveStubbing(InvocationContainerImpl invocationContainerImpl) {

-        this.invocationContainerImpl = invocationContainerImpl;

-    }

-

-    public OngoingStubbing<T> thenAnswer(Answer<?> answer) {

-        invocationContainerImpl.addConsecutiveAnswer(answer);

-        return this;

-    }

-

-    public OngoingStubbing<T> then(Answer<?> answer) {

-        return thenAnswer(answer);

-    }

-    

-    public DeprecatedOngoingStubbing<T> toAnswer(Answer<?> answer) {

-        invocationContainerImpl.addConsecutiveAnswer(answer);

-        return this;

-    }

-

-    public <M> M getMock() {

-        return (M) invocationContainerImpl.invokedMock();

-    }

-}
\ No newline at end of file
+package org.mockito.internal.stubbing;
+
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+
+public class ConsecutiveStubbing<T> extends BaseStubbing<T> {
+    private final InvocationContainerImpl invocationContainerImpl;
+
+    public ConsecutiveStubbing(InvocationContainerImpl invocationContainerImpl) {
+        this.invocationContainerImpl = invocationContainerImpl;
+    }
+
+    public OngoingStubbing<T> thenAnswer(Answer<?> answer) {
+        invocationContainerImpl.addConsecutiveAnswer(answer);
+        return this;
+    }
+
+    public OngoingStubbing<T> then(Answer<?> answer) {
+        return thenAnswer(answer);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <M> M getMock() {
+        return (M) invocationContainerImpl.invokedMock();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/InvocationContainer.java b/src/main/java/org/mockito/internal/stubbing/InvocationContainer.java
index 783ec55..b926183 100644
--- a/src/main/java/org/mockito/internal/stubbing/InvocationContainer.java
+++ b/src/main/java/org/mockito/internal/stubbing/InvocationContainer.java
@@ -2,15 +2,17 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing;

-

-import org.mockito.invocation.Invocation;

-

-import java.util.List;

-

-//TODO move to different package

-public interface InvocationContainer {

-    List<Invocation> getInvocations();

-

-    List<StubbedInvocationMatcher> getStubbedInvocations();

-}

+package org.mockito.internal.stubbing;
+
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+//TODO move to different package
+public interface InvocationContainer {
+    List<Invocation> getInvocations();
+
+    void clearInvocations();
+
+    List<StubbedInvocationMatcher> getStubbedInvocations();
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java b/src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java
index 3d45e6c..d368ede 100644
--- a/src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java
+++ b/src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java
@@ -4,35 +4,33 @@
  */
 package org.mockito.internal.stubbing;
 
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
 import org.mockito.internal.invocation.InvocationMatcher;
 import org.mockito.internal.invocation.StubInfoImpl;
-import org.mockito.internal.progress.MockingProgress;
-import org.mockito.internal.stubbing.answers.AnswersValidator;
 import org.mockito.internal.verification.DefaultRegisteredInvocations;
 import org.mockito.internal.verification.RegisteredInvocations;
 import org.mockito.internal.verification.SingleRegisteredInvocation;
 import org.mockito.invocation.Invocation;
 import org.mockito.mock.MockCreationSettings;
 import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.ValidableAnswer;
 
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
 
 @SuppressWarnings("unchecked")
 public class InvocationContainerImpl implements InvocationContainer, Serializable {
 
     private static final long serialVersionUID = -5334301962749537177L;
     private final LinkedList<StubbedInvocationMatcher> stubbed = new LinkedList<StubbedInvocationMatcher>();
-    private final MockingProgress mockingProgress;
-    private final List<Answer> answersForStubbing = new ArrayList<Answer>();
+    private final List<Answer<?>> answersForStubbing = new ArrayList<Answer<?>>();
     private final RegisteredInvocations registeredInvocations;
 
     private InvocationMatcher invocationForStubbing;
 
-    public InvocationContainerImpl(MockingProgress mockingProgress, MockCreationSettings mockSettings) {
-        this.mockingProgress = mockingProgress;
+    public InvocationContainerImpl(MockCreationSettings mockSettings) {
         this.registeredInvocations = createRegisteredInvocations(mockSettings);
     }
 
@@ -54,11 +52,15 @@
         addAnswer(answer, true);
     }
 
-    public void addAnswer(Answer answer, boolean isConsecutive) {
+    /**
+     * Adds new stubbed answer and returns the invocation matcher the answer was added to.
+     */
+    public StubbedInvocationMatcher addAnswer(Answer answer, boolean isConsecutive) {
         Invocation invocation = invocationForStubbing.getInvocation();
-        mockingProgress.stubbingCompleted(invocation);
-        AnswersValidator answersValidator = new AnswersValidator();
-        answersValidator.validate(answer, invocation);
+        mockingProgress().stubbingCompleted();
+        if (answer instanceof ValidableAnswer) {
+            ((ValidableAnswer) answer).validateFor(invocation);
+        }
 
         synchronized (stubbed) {
             if (isConsecutive) {
@@ -66,6 +68,7 @@
             } else {
                 stubbed.addFirst(new StubbedInvocationMatcher(invocationForStubbing, answer));
             }
+            return stubbed.getFirst();
         }
     }
 
@@ -91,7 +94,7 @@
         answersForStubbing.add(answer);
     }
 
-    public void setAnswersForStubbing(List<Answer> answers) {
+    public void setAnswersForStubbing(List<Answer<?>> answers) {
         answersForStubbing.addAll(answers);
     }
 
@@ -121,6 +124,10 @@
         return registeredInvocations.getAll();
     }
 
+    public void clearInvocations() {
+        registeredInvocations.clear();
+    }
+
     public List<StubbedInvocationMatcher> getStubbedInvocations() {
         return stubbed;
     }
@@ -128,9 +135,9 @@
     public Object invokedMock() {
         return invocationForStubbing.getInvocation().getMock();
     }
-    
+
     public InvocationMatcher getInvocationForStubbing() {
-    	return invocationForStubbing;
+        return invocationForStubbing;
     }
 
     private RegisteredInvocations createRegisteredInvocations(MockCreationSettings mockSettings) {
diff --git a/src/main/java/org/mockito/internal/stubbing/OngoingStubbingImpl.java b/src/main/java/org/mockito/internal/stubbing/OngoingStubbingImpl.java
index 8be71d7..3323f63 100644
--- a/src/main/java/org/mockito/internal/stubbing/OngoingStubbingImpl.java
+++ b/src/main/java/org/mockito/internal/stubbing/OngoingStubbingImpl.java
@@ -2,48 +2,44 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.invocation.Invocation;

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.DeprecatedOngoingStubbing;

-import org.mockito.stubbing.OngoingStubbing;

-

-import java.util.List;

-

-public class OngoingStubbingImpl<T> extends BaseStubbing<T> {

-    

-    private final InvocationContainerImpl invocationContainerImpl;

-

-    public OngoingStubbingImpl(InvocationContainerImpl invocationContainerImpl) {

-        this.invocationContainerImpl = invocationContainerImpl;

-    }

-

-    public OngoingStubbing<T> thenAnswer(Answer<?> answer) {

-        if(!invocationContainerImpl.hasInvocationForPotentialStubbing()) {

-            new Reporter().incorrectUseOfApi();

-        }

-

-        invocationContainerImpl.addAnswer(answer);

-        return new ConsecutiveStubbing<T>(invocationContainerImpl);

-    }

-

-    public OngoingStubbing<T> then(Answer<?> answer) {

-        return thenAnswer(answer);

-    }

-

-    public DeprecatedOngoingStubbing<T> toAnswer(Answer<?> answer) {

-        invocationContainerImpl.addAnswer(answer);

-        return new ConsecutiveStubbing<T>(invocationContainerImpl);

-    }

-

-    public List<Invocation> getRegisteredInvocations() {

-        //TODO interface for tests

-        return invocationContainerImpl.getInvocations();

-    }

-

-    public <M> M getMock() {

-        return (M) invocationContainerImpl.invokedMock();

-    }

-}

+package org.mockito.internal.stubbing;
+
+import org.mockito.invocation.Invocation;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+
+import static org.mockito.internal.exceptions.Reporter.incorrectUseOfApi;
+
+import java.util.List;
+
+public class OngoingStubbingImpl<T> extends BaseStubbing<T> {
+
+    private final InvocationContainerImpl invocationContainerImpl;
+
+    public OngoingStubbingImpl(InvocationContainerImpl invocationContainerImpl) {
+        this.invocationContainerImpl = invocationContainerImpl;
+    }
+
+    public OngoingStubbing<T> thenAnswer(Answer<?> answer) {
+        if(!invocationContainerImpl.hasInvocationForPotentialStubbing()) {
+            throw incorrectUseOfApi();
+        }
+
+        invocationContainerImpl.addAnswer(answer);
+        return new ConsecutiveStubbing<T>(invocationContainerImpl);
+    }
+
+    public OngoingStubbing<T> then(Answer<?> answer) {
+        return thenAnswer(answer);
+    }
+
+    public List<Invocation> getRegisteredInvocations() {
+        //TODO interface for tests
+        return invocationContainerImpl.getInvocations();
+    }
+
+    @SuppressWarnings("unchecked")
+    public <M> M getMock() {
+        return (M) invocationContainerImpl.invokedMock();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/StubbedInvocationMatcher.java b/src/main/java/org/mockito/internal/stubbing/StubbedInvocationMatcher.java
index 9a7cefb..98ba230 100644
--- a/src/main/java/org/mockito/internal/stubbing/StubbedInvocationMatcher.java
+++ b/src/main/java/org/mockito/internal/stubbing/StubbedInvocationMatcher.java
@@ -2,52 +2,53 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing;

-

-import java.io.Serializable;

-import java.util.Queue;

-import java.util.concurrent.ConcurrentLinkedQueue;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.DescribedInvocation;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-@SuppressWarnings("unchecked")

-public class StubbedInvocationMatcher extends InvocationMatcher implements Answer, Serializable {

-

-    private static final long serialVersionUID = 4919105134123672727L;

-    private final Queue<Answer> answers = new ConcurrentLinkedQueue<Answer>();

-    private DescribedInvocation usedAt;

-

-    public StubbedInvocationMatcher(InvocationMatcher invocation, Answer answer) {

-        super(invocation.getInvocation(), invocation.getMatchers());

-        this.answers.add(answer);

-    }

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        //see ThreadsShareGenerouslyStubbedMockTest

-        Answer a;

-        synchronized(answers) {

-            a = answers.size() == 1 ? answers.peek() : answers.poll();

-        }

-        return a.answer(invocation);

-    }

-

-    public void addAnswer(Answer answer) {

-        answers.add(answer);

-    }

-

-    public void markStubUsed(DescribedInvocation usedAt) {

-        this.usedAt = usedAt;

-    }

-

-    public boolean wasUsed() {

-        return usedAt != null;

-    }

-

-    @Override

-    public String toString() {

-        return super.toString() + " stubbed with: " + answers;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.stubbing;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.stubbing.Stubbing;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+@SuppressWarnings("unchecked")
+public class StubbedInvocationMatcher extends InvocationMatcher implements Answer, Serializable, Stubbing {
+
+    private static final long serialVersionUID = 4919105134123672727L;
+    private final Queue<Answer> answers = new ConcurrentLinkedQueue<Answer>();
+    private DescribedInvocation usedAt;
+
+    public StubbedInvocationMatcher(InvocationMatcher invocation, Answer answer) {
+        super(invocation.getInvocation(), invocation.getMatchers());
+        this.answers.add(answer);
+    }
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        //see ThreadsShareGenerouslyStubbedMockTest
+        Answer a;
+        synchronized(answers) {
+            a = answers.size() == 1 ? answers.peek() : answers.poll();
+        }
+        return a.answer(invocation);
+    }
+
+    public void addAnswer(Answer answer) {
+        answers.add(answer);
+    }
+
+    public void markStubUsed(DescribedInvocation usedAt) {
+        this.usedAt = usedAt;
+    }
+
+    public boolean wasUsed() {
+        return usedAt != null;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " stubbed with: " + answers;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/StubberImpl.java b/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
index ac8fb2e..f768cc8 100644
--- a/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
+++ b/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
@@ -2,65 +2,107 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.stubbing.answers.*;

-import org.mockito.internal.util.MockUtil;

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.Stubber;

-

-import java.util.LinkedList;

-import java.util.List;

-

-@SuppressWarnings("unchecked")

-public class StubberImpl implements Stubber {

-

-    final List<Answer> answers = new LinkedList<Answer>();

-    private final Reporter reporter = new Reporter();

-

-    public <T> T when(T mock) {

-        MockUtil mockUtil = new MockUtil();

-        

-        if (mock == null) {

-            reporter.nullPassedToWhenMethod();

-        } else {

-            if (!mockUtil.isMock(mock)) {

-                reporter.notAMockPassedToWhenMethod();

-            }

-        }

-        

-        mockUtil.getMockHandler(mock).setAnswersForStubbing(answers);

-        return mock;

-    }

-

-    public Stubber doReturn(Object toBeReturned) {

-        answers.add(new Returns(toBeReturned));

-        return this;

-    }

-

-    public Stubber doThrow(Throwable toBeThrown) {

-        answers.add(new ThrowsException(toBeThrown));

-        return this;

-    }

-

-    public Stubber doThrow(Class<? extends Throwable> toBeThrown) {

-        answers.add(new ThrowsExceptionClass(toBeThrown));

-        return this;

-    }

-

-    public Stubber doNothing() {

-        answers.add(new DoesNothing());

-        return this;

-    }

-

-    public Stubber doAnswer(Answer answer) {

-        answers.add(answer);

-        return this;

-    }

-

-    public Stubber doCallRealMethod() {

-        answers.add(new CallsRealMethods());

-        return this;

-    }

-}

+package org.mockito.internal.stubbing;
+
+import static org.mockito.internal.exceptions.Reporter.notAMockPassedToWhenMethod;
+import static org.mockito.internal.exceptions.Reporter.nullPassedToWhenMethod;
+import static org.mockito.internal.stubbing.answers.DoesNothing.doesNothing;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.internal.stubbing.answers.ThrowsExceptionClass;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
+
+@SuppressWarnings("unchecked")
+public class StubberImpl implements Stubber {
+
+    private final List<Answer<?>> answers = new LinkedList<Answer<?>>();
+
+    @Override
+    public <T> T when(T mock) {
+        if (mock == null) {
+            throw nullPassedToWhenMethod();
+        }
+
+		if (!MockUtil.isMock(mock)) {
+			throw notAMockPassedToWhenMethod();
+		}
+
+		MockUtil.getMockHandler(mock).setAnswersForStubbing(answers);
+        return mock;
+    }
+
+    @Override
+    public Stubber doReturn(Object toBeReturned) {
+        return doReturnValues(toBeReturned);
+    }
+
+    @Override
+    public Stubber doReturn(Object toBeReturned, Object... nextToBeReturned) {
+        return doReturnValues(toBeReturned).doReturnValues(nextToBeReturned);
+    }
+
+    private StubberImpl doReturnValues(Object... toBeReturned) {
+        if(toBeReturned == null) {
+            answers.add(new Returns(null));
+            return this;
+        }
+        for (Object r : toBeReturned) {
+            answers.add(new Returns(r));
+        }
+        return this;
+    }
+
+    @Override
+    public Stubber doThrow(Throwable... toBeThrown) {
+        if(toBeThrown == null) {
+            answers.add(new ThrowsException(null));
+            return this;
+        }
+        for (Throwable throwable : toBeThrown) {
+            answers.add(new ThrowsException(throwable));
+        }
+        return this;
+    }
+
+    @Override
+    public Stubber doThrow(Class<? extends Throwable> toBeThrown) {
+        return doThrowClasses(toBeThrown);
+    }
+
+    @Override
+    public Stubber doThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown) {
+        return doThrowClasses(toBeThrown).doThrowClasses(nextToBeThrown);
+    }
+
+    private StubberImpl doThrowClasses(Class<? extends Throwable>... toBeThrown) {
+        for (Class<? extends Throwable> throwable: toBeThrown) {
+            answers.add(new ThrowsExceptionClass(throwable));
+        }
+        return this;
+    }
+
+    @Override
+    public Stubber doNothing() {
+        answers.add(doesNothing());
+        return this;
+    }
+
+    @Override
+    public Stubber doAnswer(Answer answer) {
+        answers.add(answer);
+        return this;
+    }
+
+    @Override
+    public Stubber doCallRealMethod() {
+        answers.add(new CallsRealMethods());
+        return this;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/StubbingComparator.java b/src/main/java/org/mockito/internal/stubbing/StubbingComparator.java
new file mode 100644
index 0000000..b7f7ad5
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/StubbingComparator.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.internal.invocation.InvocationComparator;
+import org.mockito.stubbing.Stubbing;
+
+import java.util.Comparator;
+
+/**
+ * Compares stubbings based on {@link InvocationComparator}
+ */
+public class StubbingComparator implements Comparator<Stubbing> {
+
+    private final InvocationComparator invocationComparator = new InvocationComparator();
+
+    public int compare(Stubbing o1, Stubbing o2) {
+        return invocationComparator.compare(o1.getInvocation(), o2.getInvocation());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/VoidMethodStubbableImpl.java b/src/main/java/org/mockito/internal/stubbing/VoidMethodStubbableImpl.java
deleted file mode 100644
index 3da5a41..0000000
--- a/src/main/java/org/mockito/internal/stubbing/VoidMethodStubbableImpl.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing;

-

-import org.mockito.internal.stubbing.answers.DoesNothing;

-import org.mockito.internal.stubbing.answers.ThrowsException;

-import org.mockito.stubbing.Answer;

-import org.mockito.stubbing.VoidMethodStubbable;

-

-public class VoidMethodStubbableImpl<T> implements VoidMethodStubbable<T> {

-    private final T mock;

-    private final InvocationContainerImpl invocationContainerImpl;

-

-    public VoidMethodStubbableImpl(T mock, InvocationContainerImpl invocationContainerImpl) {

-        this.mock = mock;

-        this.invocationContainerImpl = invocationContainerImpl;

-    }

-

-    public VoidMethodStubbable<T> toThrow(Throwable throwable) {

-        invocationContainerImpl.addAnswerForVoidMethod(new ThrowsException(throwable));

-        return this;

-    }

-

-    public VoidMethodStubbable<T> toReturn() {

-        invocationContainerImpl.addAnswerForVoidMethod(new DoesNothing());

-        return this;

-    }

-

-    public VoidMethodStubbable<T> toAnswer(Answer<?> answer) {

-        invocationContainerImpl.addAnswerForVoidMethod(answer);

-        return this;

-    }

-

-    public T on() {

-        return mock;

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/AnswerFunctionalInterfaces.java b/src/main/java/org/mockito/internal/stubbing/answers/AnswerFunctionalInterfaces.java
new file mode 100644
index 0000000..e1a92a4
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/answers/AnswerFunctionalInterfaces.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Answer1;
+import org.mockito.stubbing.Answer2;
+import org.mockito.stubbing.Answer3;
+import org.mockito.stubbing.Answer4;
+import org.mockito.stubbing.Answer5;
+import org.mockito.stubbing.VoidAnswer1;
+import org.mockito.stubbing.VoidAnswer2;
+import org.mockito.stubbing.VoidAnswer3;
+import org.mockito.stubbing.VoidAnswer4;
+import org.mockito.stubbing.VoidAnswer5;
+
+/**
+ * Functional interfaces to make it easy to implement answers in Java 8
+ *
+ * @since 2.1.0
+ */
+public class AnswerFunctionalInterfaces {
+	/**
+     * Hide constructor to avoid instantiation of class with only static methods
+     */
+    private AnswerFunctionalInterfaces() {
+    }
+
+    /**
+     * Construct an answer from a two parameter answer interface
+     * @param answer answer interface
+     * @param <T> return type
+     * @param <A> input parameter 1 type
+     * @return a new answer object
+     */
+    public static <T, A> Answer<T> toAnswer(final Answer1<T, A> answer) {
+        return new Answer<T>() {
+            @SuppressWarnings("unchecked")
+            public T answer(InvocationOnMock invocation) throws Throwable {
+                return answer.answer((A)invocation.getArgument(0));
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a two parameter answer interface
+     * @param answer answer interface
+     * @param <A> input parameter 1 type
+     * @return a new answer object
+     */
+    public static <A> Answer<Void> toAnswer(final VoidAnswer1<A> answer) {
+        return new Answer<Void>() {
+            @SuppressWarnings("unchecked")
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                answer.answer((A)invocation.getArgument(0));
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a two parameter answer interface
+     * @param answer answer interface
+     * @param <T> return type
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @return a new answer object
+     */
+    public static <T, A, B> Answer<T> toAnswer(final Answer2<T, A, B> answer) {
+        return new Answer<T>() {
+            @SuppressWarnings("unchecked")
+            public T answer(InvocationOnMock invocation) throws Throwable {
+                return answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1));
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a two parameter answer interface
+     * @param answer answer interface
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @return a new answer object
+     */
+    public static <A, B> Answer<Void> toAnswer(final VoidAnswer2<A, B> answer) {
+        return new Answer<Void>() {
+            @SuppressWarnings("unchecked")
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1));
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a three parameter answer interface
+     * @param answer answer interface
+     * @param <T> return type
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @param <C> input parameter 3 type
+     * @return a new answer object
+     */
+    public static <T, A, B, C> Answer<T> toAnswer(final Answer3<T, A, B, C> answer) {
+        return new Answer<T>() {
+            @SuppressWarnings("unchecked")
+            public T answer(InvocationOnMock invocation) throws Throwable {
+                return answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1),
+                        (C)invocation.getArgument(2));
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a three parameter answer interface
+     * @param answer answer interface
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @param <C> input parameter 3 type
+     * @return a new answer object
+     */
+    public static <A, B, C> Answer<Void> toAnswer(final VoidAnswer3<A, B, C> answer) {
+        return new Answer<Void>() {
+            @SuppressWarnings("unchecked")
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1),
+                        (C)invocation.getArgument(2));
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a four parameter answer interface
+     * @param answer answer interface
+     * @param <T> return type
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @param <C> input parameter 3 type
+     * @param <D> input parameter 4 type
+     * @return a new answer object
+     */
+    public static <T, A, B, C, D> Answer<T> toAnswer(final Answer4<T, A, B, C, D> answer) {
+        return new Answer<T>() {
+            @SuppressWarnings("unchecked")
+            public T answer(InvocationOnMock invocation) throws Throwable {
+                return answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1),
+                        (C)invocation.getArgument(2),
+                        (D)invocation.getArgument(3));
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a four parameter answer interface
+     * @param answer answer interface
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @param <C> input parameter 3 type
+     * @param <D> input parameter 4 type
+     * @return a new answer object
+     */
+    public static <A, B, C, D> Answer<Void> toAnswer(final VoidAnswer4<A, B, C, D> answer) {
+        return new Answer<Void>() {
+            @SuppressWarnings("unchecked")
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1),
+                        (C)invocation.getArgument(2),
+                        (D)invocation.getArgument(3));
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a five parameter answer interface
+     * @param answer answer interface
+     * @param <T> return type
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @param <C> input parameter 3 type
+     * @param <D> input parameter 4 type
+     * @param <E> input parameter 5 type
+     * @return a new answer object
+     */
+    public static <T, A, B, C, D, E> Answer<T> toAnswer(final Answer5<T, A, B, C, D, E> answer) {
+        return new Answer<T>() {
+            @SuppressWarnings("unchecked")
+            public T answer(InvocationOnMock invocation) throws Throwable {
+                return answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1),
+                        (C)invocation.getArgument(2),
+                        (D)invocation.getArgument(3),
+                        (E)invocation.getArgument(4));
+            }
+        };
+    }
+
+    /**
+     * Construct an answer from a five parameter answer interface
+     * @param answer answer interface
+     * @param <A> input parameter 1 type
+     * @param <B> input parameter 2 type
+     * @param <C> input parameter 3 type
+     * @param <D> input parameter 4 type
+     * @param <E> input parameter 5 type
+     * @return a new answer object
+     */
+    public static <A, B, C, D, E> Answer<Void> toAnswer(final VoidAnswer5<A, B, C, D, E> answer) {
+        return new Answer<Void>() {
+            @SuppressWarnings("unchecked")
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                answer.answer(
+                        (A)invocation.getArgument(0),
+                        (B)invocation.getArgument(1),
+                        (C)invocation.getArgument(2),
+                        (D)invocation.getArgument(3),
+                        (E)invocation.getArgument(4));
+                return null;
+            }
+        };
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/AnswerReturnValuesAdapter.java b/src/main/java/org/mockito/internal/stubbing/answers/AnswerReturnValuesAdapter.java
deleted file mode 100644
index 76510cd..0000000
--- a/src/main/java/org/mockito/internal/stubbing/answers/AnswerReturnValuesAdapter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.stubbing.answers;

-

-import java.io.Serializable;

-

-import org.mockito.ReturnValues;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-//It's ok to suppress deprecation because this class goes away as soon as ReturnValues disappears in future release

-@SuppressWarnings("deprecation")

-public class AnswerReturnValuesAdapter implements Answer<Object>, Serializable {

-

-    private static final long serialVersionUID = 1418158596876713469L;

-    private final ReturnValues returnValues;

-

-    public AnswerReturnValuesAdapter(ReturnValues returnValues) {

-        this.returnValues = returnValues;

-    }

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        return returnValues.valueFor(invocation);

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/AnswersValidator.java b/src/main/java/org/mockito/internal/stubbing/answers/AnswersValidator.java
deleted file mode 100644
index 57adb38..0000000
--- a/src/main/java/org/mockito/internal/stubbing/answers/AnswersValidator.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.answers;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.invocation.Invocation;

-import org.mockito.stubbing.Answer;

-

-public class AnswersValidator {

-

-    private final Reporter reporter = new Reporter();

-    

-    public void validate(Answer<?> answer, Invocation invocation) {

-        MethodInfo methodInfo = new MethodInfo(invocation);

-        if (answer instanceof ThrowsException) {

-            validateException((ThrowsException) answer, methodInfo);

-        }

-        

-        if (answer instanceof Returns) {

-            validateReturnValue((Returns) answer, methodInfo);

-        }

-        

-        if (answer instanceof DoesNothing) {

-            validateDoNothing((DoesNothing) answer, methodInfo);

-        }

-        

-        if (answer instanceof CallsRealMethods) {

-            validateMockingConcreteClass((CallsRealMethods) answer, methodInfo);

-        }

-

-        if (answer instanceof ReturnsArgumentAt) {

-            ReturnsArgumentAt returnsArgumentAt = (ReturnsArgumentAt) answer;

-            validateReturnArgIdentity(returnsArgumentAt, invocation);

-        }

-    }

-

-    private void validateReturnArgIdentity(ReturnsArgumentAt returnsArgumentAt, Invocation invocation) {

-        returnsArgumentAt.validateIndexWithinInvocationRange(invocation);

-

-        MethodInfo methodInfo = new MethodInfo(invocation);

-        if (!methodInfo.isValidReturnType(returnsArgumentAt.returnedTypeOnSignature(invocation))) {

-            new Reporter().wrongTypeOfArgumentToReturn(invocation, methodInfo.printMethodReturnType(),

-                                                       returnsArgumentAt.returnedTypeOnSignature(invocation),

-                                                       returnsArgumentAt.wantedArgumentPosition());

-        }

-

-    }

-

-    private void validateMockingConcreteClass(CallsRealMethods answer, MethodInfo methodInfo) {

-        if (methodInfo.isAbstract()) {

-            reporter.cannotCallAbstractRealMethod();

-        }

-    }

-

-    private void validateDoNothing(DoesNothing answer, MethodInfo methodInfo) {

-        if (!methodInfo.isVoid()) {

-            reporter.onlyVoidMethodsCanBeSetToDoNothing();

-        }

-    }

-

-    private void validateReturnValue(Returns answer, MethodInfo methodInfo) {

-        if (methodInfo.isVoid()) {

-            reporter.cannotStubVoidMethodWithAReturnValue(methodInfo.getMethodName());

-        }

-        

-        if (answer.returnsNull() && methodInfo.returnsPrimitive()) {

-            reporter.wrongTypeOfReturnValue(methodInfo.printMethodReturnType(), "null", methodInfo.getMethodName());

-        } 

-

-        if (!answer.returnsNull() && !methodInfo.isValidReturnType(answer.getReturnType())) {

-            reporter.wrongTypeOfReturnValue(methodInfo.printMethodReturnType(), answer.printReturnType(), methodInfo.getMethodName());

-        }

-    }

-

-    private void validateException(ThrowsException answer, MethodInfo methodInfo) {

-        Throwable throwable = answer.getThrowable();

-        if (throwable == null) {

-            reporter.cannotStubWithNullThrowable();

-        }

-        

-        if (throwable instanceof RuntimeException || throwable instanceof Error) {

-            return;

-        }

-        

-        if (!methodInfo.isValidException(throwable)) {

-            reporter.checkedExceptionInvalid(throwable);

-        }

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/CallsRealMethods.java b/src/main/java/org/mockito/internal/stubbing/answers/CallsRealMethods.java
index 167e67b..59a82e6 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/CallsRealMethods.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/CallsRealMethods.java
@@ -1,43 +1,52 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.answers;

-

-import org.mockito.Answers;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-import java.io.Serializable;

-import java.lang.reflect.Modifier;

-

-/**

- * Optional Answer that adds partial mocking support

- * <p>

- * {@link Answer} can be used to define the return values of unstubbed invocations.

- * <p>

- * This implementation can be helpful when working with legacy code.

- * When this implementation is used, unstubbed methods will delegate to the real implementation.

- * This is a way to create a partial mock object that calls real methods by default.

- * <p>

- * As usual you are going to read <b>the partial mock warning</b>:

- * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.

- * How does partial mock fit into this paradigm? Well, it just doesn't... 

- * Partial mock usually means that the complexity has been moved to a different method on the same object.

- * In most cases, this is not the way you want to design your application.

- * <p>

- * However, there are rare cases when partial mocks come handy: 

- * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)

- * However, I wouldn't use partial mocks for new, test-driven & well-designed code.

- * <p>

- */

-public class CallsRealMethods implements Answer<Object>, Serializable {

-    private static final long serialVersionUID = 9057165148930624087L;

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-    	if (Modifier.isAbstract(invocation.getMethod().getModifiers())) {

-    		return Answers.RETURNS_DEFAULTS.get().answer(invocation);

-    	}

-        return invocation.callRealMethod();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+import java.lang.reflect.Modifier;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.ValidableAnswer;
+
+import static org.mockito.Answers.RETURNS_DEFAULTS;
+import static org.mockito.internal.exceptions.Reporter.cannotCallAbstractRealMethod;
+
+/**
+ * Optional Answer that adds partial mocking support
+ * <p>
+ * {@link Answer} can be used to define the return values of unstubbed invocations.
+ * <p>
+ * This implementation can be helpful when working with legacy code.
+ * When this implementation is used, unstubbed methods will delegate to the real implementation.
+ * This is a way to create a partial mock object that calls real methods by default.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <p>
+ */
+public class CallsRealMethods implements Answer<Object>, ValidableAnswer, Serializable {
+    private static final long serialVersionUID = 9057165148930624087L;
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        if (Modifier.isAbstract(invocation.getMethod().getModifiers())) {
+            return RETURNS_DEFAULTS.answer(invocation);
+        }
+        return invocation.callRealMethod();
+    }
+
+    @Override
+    public void validateFor(InvocationOnMock invocation) {
+        if (new InvocationInfo(invocation).isAbstract()) {
+            throw cannotCallAbstractRealMethod();
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ClonesArguments.java b/src/main/java/org/mockito/internal/stubbing/answers/ClonesArguments.java
index f6fa264..7296095 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ClonesArguments.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ClonesArguments.java
@@ -2,25 +2,27 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing.answers;

-

-import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;

-import org.mockito.internal.util.reflection.LenientCopyTool;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-import org.objenesis.ObjenesisHelper;

-

-//TODO this needs documentation and further analysis - what if someone changes the answer?

-//we might think about implementing it straight on MockSettings

-public class ClonesArguments implements Answer<Object> {

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        Object[] arguments = invocation.getArguments();

-        for (int i = 0; i < arguments.length; i++) {

-            Object from = arguments[i];

-            Object newInstance = ObjenesisHelper.newInstance(from.getClass());

-            new LenientCopyTool().copyToRealObject(from, newInstance);

-            arguments[i] = newInstance;

-        }

-        return new ReturnsEmptyValues().answer(invocation);

-    }

-}
\ No newline at end of file
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.internal.creation.instance.Instantiator;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.internal.util.reflection.LenientCopyTool;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+//TODO this needs documentation and further analysis - what if someone changes the answer?
+//we might think about implementing it straight on MockSettings
+public class ClonesArguments implements Answer<Object> {
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        Object[] arguments = invocation.getArguments();
+        for (int i = 0; i < arguments.length; i++) {
+            Object from = arguments[i];
+            Instantiator instantiator = Plugins.getInstantiatorProvider().getInstantiator(null);
+            Object newInstance = instantiator.newInstance(from.getClass());
+            new LenientCopyTool().copyToRealObject(from, newInstance);
+            arguments[i] = newInstance;
+        }
+        return new ReturnsEmptyValues().answer(invocation);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidator.java b/src/main/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidator.java
new file mode 100644
index 0000000..da1d2a7
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidator.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.invocation.InvocationOnMock;
+
+import static org.mockito.internal.exceptions.Reporter.wrongTypeReturnedByDefaultAnswer;
+
+public abstract class DefaultAnswerValidator {
+    public static void validateReturnValueFor(InvocationOnMock invocation, Object returnedValue) throws Throwable {
+        InvocationInfo invocationInfo = new InvocationInfo(invocation);
+        if (returnedValue != null && !invocationInfo.isValidReturnType(returnedValue.getClass())) {
+            throw wrongTypeReturnedByDefaultAnswer(
+                    invocation.getMock(),
+                    invocationInfo.printMethodReturnType(),
+                    returnedValue.getClass().getSimpleName(),
+                    invocationInfo.getMethodName());
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java b/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java
index d9a7d7a..bc625fb 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java
@@ -2,18 +2,37 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing.answers;

-

-import java.io.Serializable;

-

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-public class DoesNothing implements Answer<Object>, Serializable {

-    

-    private static final long serialVersionUID = 4840880517740698416L;

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        return null;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.ValidableAnswer;
+
+import static org.mockito.internal.exceptions.Reporter.onlyVoidMethodsCanBeSetToDoNothing;
+
+public class DoesNothing implements Answer<Object>, ValidableAnswer, Serializable {
+
+    private static final long serialVersionUID = 4840880517740698416L;
+
+    private static final DoesNothing SINGLETON = new DoesNothing();
+
+    private DoesNothing() {}
+
+    public static DoesNothing doesNothing(){
+        return SINGLETON;
+    }
+
+    @Override
+    public Object answer(InvocationOnMock invocation){
+        return null;
+    }
+
+    @Override
+    public void validateFor(InvocationOnMock invocation) {
+        if (!new InvocationInfo(invocation).isVoid()) {
+            throw onlyVoidMethodsCanBeSetToDoNothing();
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java b/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java
new file mode 100644
index 0000000..11498b7
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import org.mockito.internal.invocation.AbstractAwareMethod;
+import org.mockito.internal.util.Primitives;
+import org.mockito.invocation.InvocationOnMock;
+
+public class InvocationInfo implements AbstractAwareMethod {
+
+    private final Method method;
+
+    public InvocationInfo(InvocationOnMock theInvocation) {
+        this.method = theInvocation.getMethod();
+    }
+
+    public boolean isValidException(Throwable throwable) {
+        Class<?>[] exceptions = method.getExceptionTypes();
+        Class<?> throwableClass = throwable.getClass();
+        for (Class<?> exception : exceptions) {
+            if (exception.isAssignableFrom(throwableClass)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isValidReturnType(Class<?> clazz) {
+        if (method.getReturnType().isPrimitive() || clazz.isPrimitive()) {
+            return Primitives.primitiveTypeOf(clazz) == Primitives.primitiveTypeOf(method.getReturnType());
+        } else {
+            return method.getReturnType().isAssignableFrom(clazz);
+        }
+    }
+
+    /**
+     * Returns {@code true} is the return type is {@link Void} or represents the pseudo-type to the keyword {@code void}.
+     * E.g:  {@code void foo()} or {@code Void bar()}
+     */
+    public boolean isVoid() {
+        Class<?> returnType = this.method.getReturnType();
+        return returnType == Void.TYPE|| returnType == Void.class;
+    }
+
+    public String printMethodReturnType() {
+        return method.getReturnType().getSimpleName();
+    }
+
+    public String getMethodName() {
+        return method.getName();
+    }
+
+    public boolean returnsPrimitive() {
+        return method.getReturnType().isPrimitive();
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+
+    public boolean isDeclaredOnInterface() {
+        return method.getDeclaringClass().isInterface();
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return (method.getModifiers() & Modifier.ABSTRACT) != 0;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/MethodInfo.java b/src/main/java/org/mockito/internal/stubbing/answers/MethodInfo.java
deleted file mode 100644
index 39b2f51..0000000
--- a/src/main/java/org/mockito/internal/stubbing/answers/MethodInfo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.stubbing.answers;
-
-import org.mockito.internal.invocation.AbstractAwareMethod;
-import org.mockito.internal.util.Primitives;
-import org.mockito.invocation.Invocation;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-/**
- * by Szczepan Faber, created at: 3/31/12
- */
-public class MethodInfo implements AbstractAwareMethod {
-
-    private final Method method;
-
-    public MethodInfo(Invocation theInvocation) {
-        this.method = theInvocation.getMethod();
-    }
-
-    public boolean isValidException(Throwable throwable) {
-        Class<?>[] exceptions = method.getExceptionTypes();
-        Class<?> throwableClass = throwable.getClass();
-        for (Class<?> exception : exceptions) {
-            if (exception.isAssignableFrom(throwableClass)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean isValidReturnType(Class clazz) {
-        if (method.getReturnType().isPrimitive() || clazz.isPrimitive()) {
-            return Primitives.primitiveTypeOf(clazz) == Primitives.primitiveTypeOf(method.getReturnType());
-        } else {
-            return method.getReturnType().isAssignableFrom(clazz);
-        }
-    }
-
-    public boolean isVoid() {
-        return this.method.getReturnType() == Void.TYPE;
-    }
-
-    public String printMethodReturnType() {
-        return method.getReturnType().getSimpleName();
-    }
-
-    public String getMethodName() {
-        return method.getName();
-    }
-
-    public boolean returnsPrimitive() {
-        return method.getReturnType().isPrimitive();
-    }
-
-    public Method getMethod() {
-        return method;
-    }
-
-    public boolean isDeclaredOnInterface() {
-        return method.getDeclaringClass().isInterface();
-    }
-
-    public boolean isAbstract() {
-        return (method.getModifiers() & Modifier.ABSTRACT) != 0;
-    }
-}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/Returns.java b/src/main/java/org/mockito/internal/stubbing/answers/Returns.java
index b0ad9fa..f34003b 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/Returns.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/Returns.java
@@ -2,40 +2,60 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing.answers;

-

-import java.io.Serializable;

-

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-public class Returns implements Answer<Object>, Serializable {

-

-    private static final long serialVersionUID = -6245608253574215396L;

-    private final Object value;

-

-    public Returns(Object value) {

-        this.value = value;

-    }

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        return value;

-    }

-

-    public String printReturnType() {

-        return value.getClass().getSimpleName();

-    }

-

-    public Class<?> getReturnType() {

-        return value.getClass();

-    }

-

-    public boolean returnsNull() {

-        return value == null;

-    }

-    

-    @Override

-    public String toString() {

-        return "Returns: " + value;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.ValidableAnswer;
+
+import static org.mockito.internal.exceptions.Reporter.cannotStubVoidMethodWithAReturnValue;
+import static org.mockito.internal.exceptions.Reporter.wrongTypeOfReturnValue;
+
+public class Returns implements Answer<Object>, ValidableAnswer, Serializable {
+
+    private static final long serialVersionUID = -6245608253574215396L;
+    private final Object value;
+
+    public Returns(Object value) {
+        this.value = value;
+    }
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        return value;
+    }
+
+    @Override
+    public void validateFor(InvocationOnMock invocation) {
+        InvocationInfo invocationInfo = new InvocationInfo(invocation);
+        if (invocationInfo.isVoid()) {
+            throw cannotStubVoidMethodWithAReturnValue(invocationInfo.getMethodName());
+        }
+
+        if (returnsNull() && invocationInfo.returnsPrimitive()) {
+            throw wrongTypeOfReturnValue(invocationInfo.printMethodReturnType(), "null", invocationInfo.getMethodName());
+        }
+
+        if (!returnsNull() && !invocationInfo.isValidReturnType(returnType())) {
+            throw wrongTypeOfReturnValue(invocationInfo.printMethodReturnType(), printReturnType(), invocationInfo.getMethodName());
+        }
+    }
+
+    private String printReturnType() {
+        return value.getClass().getSimpleName();
+    }
+
+    private Class<?> returnType() {
+        return value.getClass();
+    }
+
+    private boolean returnsNull() {
+        return value == null;
+    }
+
+    @Override
+    public String toString() {
+        return "Returns: " + value;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java b/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
index 059074d..7c0a144 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
@@ -4,22 +4,24 @@
  */
 package org.mockito.internal.stubbing.answers;
 
-import org.mockito.exceptions.Reporter;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import org.mockito.internal.exceptions.Reporter;
+import org.mockito.invocation.Invocation;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-
-import java.io.Serializable;
+import org.mockito.stubbing.ValidableAnswer;
 
 /**
  * Returns the passed parameter identity at specified index.
- *
+ * <p>
  * <p>The <code>argumentIndex</code> represents the index in the argument array of the invocation.</p>
  * <p>If this number equals -1 then the last argument is returned.</p>
  *
  * @see org.mockito.AdditionalAnswers
  * @since 1.9.5
  */
-public class ReturnsArgumentAt implements Answer<Object>, Serializable {
+public class ReturnsArgumentAt implements Answer<Object>, ValidableAnswer, Serializable {
 
     private static final long serialVersionUID = -589315085166295101L;
 
@@ -31,81 +33,102 @@
      * Build the identity answer to return the argument at the given position in the argument array.
      *
      * @param wantedArgumentPosition The position of the argument identity to return in the invocation.
-     *                      Using <code>-1</code> indicates the last argument.
+     *                               Using <code>-1</code> indicates the last argument ({@link #LAST_ARGUMENT}).
      */
     public ReturnsArgumentAt(int wantedArgumentPosition) {
-        this.wantedArgumentPosition = checkWithinAllowedRange(wantedArgumentPosition);
-    }
-
-    public Object answer(InvocationOnMock invocation) throws Throwable {
-        validateIndexWithinInvocationRange(invocation);
-        return invocation.getArguments()[actualArgumentPosition(invocation)];
-    }
-
-
-    private int actualArgumentPosition(InvocationOnMock invocation) {
-        return returningLastArg() ?
-                lastArgumentIndexOf(invocation) :
-                argumentIndexOf(invocation);
-    }
-
-    private boolean returningLastArg() {
-        return wantedArgumentPosition == LAST_ARGUMENT;
-    }
-
-    private int argumentIndexOf(InvocationOnMock invocation) {
-        return wantedArgumentPosition;
-    }
-
-    private int lastArgumentIndexOf(InvocationOnMock invocation) {
-        return invocation.getArguments().length - 1;
-    }
-
-    private int checkWithinAllowedRange(int argumentPosition) {
-        if (argumentPosition != LAST_ARGUMENT && argumentPosition < 0) {
-            new Reporter().invalidArgumentRangeAtIdentityAnswerCreationTime();
+        if (wantedArgumentPosition != LAST_ARGUMENT && wantedArgumentPosition < 0) {
+            throw Reporter.invalidArgumentRangeAtIdentityAnswerCreationTime();
         }
-        return argumentPosition;
+        this.wantedArgumentPosition = wantedArgumentPosition;
     }
 
-    public int wantedArgumentPosition() {
-        return wantedArgumentPosition;
+    @Override
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        int argumentPosition = inferWantedArgumentPosition(invocation);
+        validateIndexWithinInvocationRange(invocation, argumentPosition);
+
+        if (wantedArgIndexIsVarargAndSameTypeAsReturnType(invocation.getMethod(), argumentPosition)) {
+            // answer raw vararg array argument
+            return ((Invocation) invocation).getRawArguments()[argumentPosition];
+        } else {
+            // answer expanded argument at wanted position
+            return invocation.getArgument(argumentPosition);
+        }
     }
 
-    public void validateIndexWithinInvocationRange(InvocationOnMock invocation) {
-        if (!argumentPositionInRange(invocation)) {
-            new Reporter().invalidArgumentPositionRangeAtInvocationTime(invocation,
-                                                                        returningLastArg(),
+    @Override
+    public void validateFor(InvocationOnMock invocation) {
+        int argumentPosition = inferWantedArgumentPosition(invocation);
+        validateIndexWithinInvocationRange(invocation, argumentPosition);
+        validateArgumentTypeCompatibility(invocation, argumentPosition);
+    }
+
+    private int inferWantedArgumentPosition(InvocationOnMock invocation) {
+        return wantedArgumentPosition == LAST_ARGUMENT ?
+               invocation.getArguments().length - 1 :
+               wantedArgumentPosition;
+    }
+
+    private void validateIndexWithinInvocationRange(InvocationOnMock invocation, int argumentPosition) {
+        if (!wantedArgumentPositionIsValidForInvocation(invocation, argumentPosition)) {
+            throw Reporter.invalidArgumentPositionRangeAtInvocationTime(invocation,
+                                                                        wantedArgumentPosition == LAST_ARGUMENT,
                                                                         wantedArgumentPosition);
         }
     }
 
-    private boolean argumentPositionInRange(InvocationOnMock invocation) {
-        int actualArgumentPosition = actualArgumentPosition(invocation);
-        if (actualArgumentPosition < 0) {
+    private void validateArgumentTypeCompatibility(InvocationOnMock invocation, int argumentPosition) {
+        InvocationInfo invocationInfo = new InvocationInfo(invocation);
+        Class<?> inferredArgumentType = inferWantedArgumentType(invocation, argumentPosition);
+        if (!invocationInfo.isValidReturnType(inferredArgumentType)) {
+            throw Reporter.wrongTypeOfArgumentToReturn(invocation,
+                                                       invocationInfo.printMethodReturnType(),
+                                                       inferredArgumentType,
+                                                       wantedArgumentPosition);
+        }
+    }
+
+    private boolean wantedArgIndexIsVarargAndSameTypeAsReturnType(Method method, int argumentPosition) {
+        Class<?>[] parameterTypes = method.getParameterTypes();
+        return method.isVarArgs()
+               && argumentPosition == /* vararg index */ parameterTypes.length - 1
+               && method.getReturnType().isAssignableFrom(parameterTypes[argumentPosition]);
+    }
+
+    private boolean wantedArgumentPositionIsValidForInvocation(InvocationOnMock invocation, int argumentPosition) {
+        if (argumentPosition < 0) {
             return false;
         }
         if (!invocation.getMethod().isVarArgs()) {
-            return invocation.getArguments().length > actualArgumentPosition;
+            return invocation.getArguments().length > argumentPosition;
         }
         // for all varargs accepts positive ranges
         return true;
     }
 
-    public Class returnedTypeOnSignature(InvocationOnMock invocation) {
-        int actualArgumentPosition = actualArgumentPosition(invocation);
-
-        if(!invocation.getMethod().isVarArgs()) {
-            return invocation.getMethod().getParameterTypes()[actualArgumentPosition];
+    private Class<?> inferWantedArgumentType(InvocationOnMock invocation, int argumentPosition) {
+        Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
+        // Easy when the method is not a vararg
+        if (!invocation.getMethod().isVarArgs()) {
+            return parameterTypes[argumentPosition];
         }
 
-        Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
-        int varargPosition = parameterTypes.length - 1;
+        // Now for varargs
+        int varargIndex = parameterTypes.length - 1; // vararg always last
 
-        if(actualArgumentPosition < varargPosition) {
-            return parameterTypes[actualArgumentPosition];
+        if (argumentPosition < varargIndex) {
+            // Same for non vararg arguments
+            return parameterTypes[argumentPosition];
         } else {
-            return parameterTypes[varargPosition].getComponentType();
+            // if wanted argument is vararg
+            if (wantedArgIndexIsVarargAndSameTypeAsReturnType(invocation.getMethod(), argumentPosition)) {
+                // return the vararg array if return type is compatible
+                // because the user probably want to return the array itself if the return type is compatible
+                return parameterTypes[argumentPosition]; // move to MethodInfo ?
+            } else {
+                // return the type in this vararg array
+                return parameterTypes[varargIndex].getComponentType();
+            }
         }
     }
 }
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java b/src/main/java/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java
index b6e1659..aaf6750 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java
@@ -1,51 +1,50 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.answers;

-

-import org.mockito.exceptions.base.MockitoException;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-import java.util.Collection;

-import java.util.LinkedList;

-

-/**

- * Returns elements of the collection. Keeps returning the last element forever.

- * Might be useful on occasion when you have a collection of elements to return.

- * <p>

- * <pre class="code"><code class="java">

- *   //this:

- *   when(mock.foo()).thenReturn(1, 2, 3);

- *   //is equivalent to:

- *   when(mock.foo()).thenAnswer(new ReturnsElementsOf(Arrays.asList(1, 2, 3)));

- * </code></pre>

- * </p>

- *

- * <p>

- * Also you might better want to use the static factory there

- * {@link org.mockito.AdditionalAnswers#returnsElementsOf(java.util.Collection)}

- * </p>

- *

- * @see org.mockito.AdditionalAnswers

- */

-public class ReturnsElementsOf implements Answer<Object> {

-

-    private final LinkedList<Object> elements;

-

-    public ReturnsElementsOf(Collection<?> elements) {

-        if (elements == null) {

-            throw new MockitoException("ReturnsElementsOf does not accept null as constructor argument.\n" +

-            		"Please pass a collection instance");

-        }

-        this.elements = new LinkedList<Object>(elements);

-    }

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        if (elements.size() == 1)

-            return elements.get(0);

-        else 

-            return elements.poll();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Returns elements of the collection. Keeps returning the last element forever.
+ * Might be useful on occasion when you have a collection of elements to return.
+ * <p>
+ * <pre class="code"><code class="java">
+ *   //this:
+ *   when(mock.foo()).thenReturn(1, 2, 3);
+ *   //is equivalent to:
+ *   when(mock.foo()).thenAnswer(new ReturnsElementsOf(Arrays.asList(1, 2, 3)));
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * Also you might better want to use the static factory there
+ * {@link org.mockito.AdditionalAnswers#returnsElementsOf(java.util.Collection)}
+ * </p>
+ *
+ * @see org.mockito.AdditionalAnswers
+ */
+public class ReturnsElementsOf implements Answer<Object> {
+
+    private final LinkedList<Object> elements;
+
+    public ReturnsElementsOf(Collection<?> elements) {
+        if (elements == null) {
+            throw new MockitoException("ReturnsElementsOf does not accept null as constructor argument.\n" +
+                    "Please pass a collection instance");
+        }
+        this.elements = new LinkedList<Object>(elements);
+    }
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        if (elements.size() == 1)
+            return elements.get(0);
+        else
+            return elements.poll();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java b/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java
index b1ed1b2..037520f 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java
@@ -1,36 +1,54 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.answers;

-

-import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;

-import org.mockito.internal.util.MockUtil;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-import java.io.Serializable;

-

-public class ThrowsException implements Answer<Object>, Serializable {

-

-    private static final long serialVersionUID = 1128820328555183980L;

-    private final Throwable throwable;

-    private final ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();

-

-    public ThrowsException(Throwable throwable) {

-        this.throwable = throwable;

-    }

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        if (new MockUtil().isMock(throwable)) {

-            throw throwable;

-        }

-        Throwable t = throwable.fillInStackTrace();

-        filter.filter(t);

-        throw t;

-    }

-

-    public Throwable getThrowable() {

-        return throwable;

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.ValidableAnswer;
+
+import static org.mockito.internal.exceptions.Reporter.cannotStubWithNullThrowable;
+import static org.mockito.internal.exceptions.Reporter.checkedExceptionInvalid;
+
+public class ThrowsException implements Answer<Object>, ValidableAnswer, Serializable {
+
+    private static final long serialVersionUID = 1128820328555183980L;
+    private final Throwable throwable;
+    private final ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+
+    public ThrowsException(Throwable throwable) {
+        this.throwable = throwable;
+    }
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        if (MockUtil.isMock(throwable)) {
+            throw throwable;
+        }
+        Throwable t = throwable.fillInStackTrace();
+
+        if (t == null) {
+            throw throwable;
+        }
+        filter.filter(t);
+        throw t;
+    }
+
+    @Override
+    public void validateFor(InvocationOnMock invocation) {
+        if (throwable == null) {
+            throw cannotStubWithNullThrowable();
+        }
+
+        if (throwable instanceof RuntimeException || throwable instanceof Error) {
+            return;
+        }
+
+        if (!new InvocationInfo(invocation).isValidException(throwable)) {
+            throw checkedExceptionInvalid(throwable);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java b/src/main/java/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java
index 1059844..ef7baad 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java
@@ -10,6 +10,8 @@
 import org.mockito.stubbing.Answer;
 import org.objenesis.ObjenesisHelper;
 
+import static org.mockito.internal.exceptions.Reporter.notAnException;
+
 import java.io.Serializable;
 
 public class ThrowsExceptionClass implements Answer<Object>, Serializable {
@@ -18,12 +20,19 @@
     private final ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
 
     public ThrowsExceptionClass(Class<? extends Throwable> throwableClass) {
-        this.throwableClass = throwableClass;
+        this.throwableClass = checkNonNullThrowable(throwableClass);
+    }
+
+    private Class<? extends Throwable> checkNonNullThrowable(Class<? extends Throwable> throwableClass) {
+        if(throwableClass == null || !Throwable.class.isAssignableFrom(throwableClass)) {
+            throw notAnException();
+        }
+        return throwableClass;
     }
 
     public Object answer(InvocationOnMock invocation) throws Throwable {
         //TODO centralize the use of Objenesis. Why do we use ObjenesisHelper?
-        Throwable throwable = (Throwable) ObjenesisHelper.newInstance(throwableClass);
+        Throwable throwable = ObjenesisHelper.newInstance(throwableClass);
         throwable.fillInStackTrace();
         filter.filter(throwable);
         throw throwable;
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/package-info.java b/src/main/java/org/mockito/internal/stubbing/answers/package-info.java
new file mode 100644
index 0000000..d44b44d
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/answers/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Answers for stubbed calls.
+ */
+package org.mockito.internal.stubbing.answers;
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/package.html b/src/main/java/org/mockito/internal/stubbing/answers/package.html
deleted file mode 100644
index 3fdeb8d..0000000
--- a/src/main/java/org/mockito/internal/stubbing/answers/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Answers for stubbed calls
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/Answers.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/Answers.java
deleted file mode 100644
index a72d583..0000000
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/Answers.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.defaultanswers;

-

-import org.mockito.Mockito;

-import org.mockito.internal.stubbing.answers.CallsRealMethods;

-import org.mockito.stubbing.Answer;

-

-/**

- * Enumeration of pre-configured mock answers

- * <p>

- * @deprecated - please use Answers from top Mockito package: {@link org.mockito.Answers}

- * <p>

- * <b>WARNING</b> Those answers no longer are used by the framework!!! Please use {@link org.mockito.Answers}

- * <p>

- * See {@link Mockito} for more information.

- */

-@Deprecated

-public enum Answers {

-

-    RETURNS_DEFAULTS(new GloballyConfiguredAnswer()),

-    RETURNS_SMART_NULLS(new ReturnsSmartNulls()),

-    RETURNS_MOCKS(new ReturnsMocks()),

-    RETURNS_DEEP_STUBS(new ReturnsDeepStubs()),

-    CALLS_REAL_METHODS(new CallsRealMethods())

-	;

-

-    private final Answer<Object> implementation;

-

-    private Answers(Answer<Object> implementation) {

-        this.implementation = implementation;

-    }

-

-    public Answer<Object> get() {

-        return implementation;

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
index df86442..9165142 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
@@ -4,14 +4,14 @@
  */
 package org.mockito.internal.stubbing.defaultanswers;
 
+import static org.mockito.internal.exceptions.Reporter.delegatedMethodDoesNotExistOnDelegate;
+import static org.mockito.internal.exceptions.Reporter.delegatedMethodHasWrongReturnType;
+
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
-import org.mockito.exceptions.Reporter;
-import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.stubbing.answers.MethodInfo;
-import org.mockito.internal.util.Primitives;
+import org.mockito.invocation.Invocation;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -31,25 +31,22 @@
 
     public Object answer(InvocationOnMock invocation) throws Throwable {
         Method mockMethod = invocation.getMethod();
-        
-        Object result = null;
-        
+
         try {
             Method delegateMethod = getDelegateMethod(mockMethod);
-            
+
             if (!compatibleReturnTypes(mockMethod.getReturnType(), delegateMethod.getReturnType())) {
-                new Reporter().delegatedMethodHasWrongReturnType(mockMethod, delegateMethod, invocation.getMock(), delegatedObject);
+                throw delegatedMethodHasWrongReturnType(mockMethod, delegateMethod, invocation.getMock(), delegatedObject);
             }
-            
-            result = delegateMethod.invoke(delegatedObject, invocation.getArguments());
+
+            Object[] rawArguments = ((Invocation) invocation).getRawArguments();
+            return delegateMethod.invoke(delegatedObject, rawArguments);
         } catch (NoSuchMethodException e) {
-            new Reporter().delegatedMethodDoesNotExistOnDelegate(mockMethod, invocation.getMock(), delegatedObject);
+            throw delegatedMethodDoesNotExistOnDelegate(mockMethod, invocation.getMock(), delegatedObject);
         } catch (InvocationTargetException e) {
             // propagate the original exception from the delegate
             throw e.getCause();
         }
-        
-        return result;
     }
 
     private Method getDelegateMethod(Method mockMethod) throws NoSuchMethodException {
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java
index 8e80750..a25832f 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java
@@ -2,25 +2,25 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing.defaultanswers;

-

-import java.io.Serializable;

-

-import org.mockito.configuration.IMockitoConfiguration;

-import org.mockito.internal.configuration.GlobalConfiguration;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-/**

- * Globally configured Answer.

- * <p>

- * See javadoc for {@link IMockitoConfiguration}

- */

-public class GloballyConfiguredAnswer implements Answer<Object>, Serializable {

-    

-    private static final long serialVersionUID = 3585893470101750917L;

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        return new GlobalConfiguration().getDefaultAnswer().answer(invocation);

-    }

-}

+package org.mockito.internal.stubbing.defaultanswers;
+
+import java.io.Serializable;
+
+import org.mockito.configuration.IMockitoConfiguration;
+import org.mockito.internal.configuration.GlobalConfiguration;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Globally configured Answer.
+ * <p>
+ * See javadoc for {@link IMockitoConfiguration}
+ */
+public class GloballyConfiguredAnswer implements Answer<Object>, Serializable {
+
+    private static final long serialVersionUID = 3585893470101750917L;
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        return new GlobalConfiguration().getDefaultAnswer().answer(invocation);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java
index 3bb7636..84cd957 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java
@@ -1,167 +1,173 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.defaultanswers;

-

-import org.mockito.MockSettings;

-import org.mockito.Mockito;

-import org.mockito.internal.InternalMockHandler;

-import org.mockito.internal.MockitoCore;

-import org.mockito.internal.creation.settings.CreationSettings;

-import org.mockito.internal.stubbing.InvocationContainerImpl;

-import org.mockito.internal.stubbing.StubbedInvocationMatcher;

-import org.mockito.internal.util.MockUtil;

-import org.mockito.internal.util.reflection.GenericMetadataSupport;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.mock.MockCreationSettings;

-import org.mockito.stubbing.Answer;

-

-import java.io.IOException;

-import java.io.Serializable;

-

-import static org.mockito.Mockito.withSettings;

-

-/**

- * Returning deep stub implementation.

- *

- * Will return previously created mock if the invocation matches.

- *

- * <p>Supports nested generic information, with this answer you can write code like this :

- *

- * <pre class="code"><code class="java">

- *     interface GenericsNest&lt;K extends Comparable&lt;K&gt; & Cloneable&gt; extends Map&lt;K, Set&lt;Number&gt;&gt; {}

- *

- *     GenericsNest&lt;?&gt; mock = mock(GenericsNest.class, new ReturnsGenericDeepStubs());

- *     Number number = mock.entrySet().iterator().next().getValue().iterator().next();

- * </code></pre>

- * </p>

- *

- * @see org.mockito.Mockito#RETURNS_DEEP_STUBS

- * @see org.mockito.Answers#RETURNS_DEEP_STUBS

- */

-public class ReturnsDeepStubs implements Answer<Object>, Serializable {

-

-    private static final long serialVersionUID = -7105341425736035847L;

-

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        GenericMetadataSupport returnTypeGenericMetadata =

-                actualParameterizedType(invocation.getMock()).resolveGenericReturnType(invocation.getMethod());

-

-        Class<?> rawType = returnTypeGenericMetadata.rawType();

-        if (!mockitoCore().isTypeMockable(rawType)) {

-            return delegate().returnValueFor(rawType);

-        }

-

-        return deepStub(invocation, returnTypeGenericMetadata);

-    }

-

-    private Object deepStub(InvocationOnMock invocation, GenericMetadataSupport returnTypeGenericMetadata) throws Throwable {

-        InternalMockHandler<Object> handler = new MockUtil().getMockHandler(invocation.getMock());

-        InvocationContainerImpl container = (InvocationContainerImpl) handler.getInvocationContainer();

-

-        // matches invocation for verification

-        for (StubbedInvocationMatcher stubbedInvocationMatcher : container.getStubbedInvocations()) {

-            if (container.getInvocationForStubbing().matches(stubbedInvocationMatcher.getInvocation())) {

-                return stubbedInvocationMatcher.answer(invocation);

-            }

-        }

-

-        // record deep stub answer

-        return recordDeepStubAnswer(

-                newDeepStubMock(returnTypeGenericMetadata, invocation.getMock()),

-                container

-        );

-    }

-

-    /**

-     * Creates a mock using the Generics Metadata.

-     *

-     * <li>Finally as we want to mock the actual type, but we want to pass along the contextual generics meta-data

-     * that was resolved for the current return type, for this to happen we associate to the mock an new instance of

-     * {@link ReturnsDeepStubs} answer in which we will store the returned type generic metadata.

-     *

-     * @param returnTypeGenericMetadata The metadata to use to create the new mock.

-     * @param parentMock The parent of the current deep stub mock.

-     * @return The mock

-     */

-    private Object newDeepStubMock(GenericMetadataSupport returnTypeGenericMetadata, Object parentMock) {

-        MockCreationSettings parentMockSettings = new MockUtil().getMockSettings(parentMock);

-        return mockitoCore().mock(

-                returnTypeGenericMetadata.rawType(),

-                withSettingsUsing(returnTypeGenericMetadata, parentMockSettings)

-        );

-    }

-

-    private MockSettings withSettingsUsing(GenericMetadataSupport returnTypeGenericMetadata, MockCreationSettings parentMockSettings) {

-        MockSettings mockSettings = returnTypeGenericMetadata.hasRawExtraInterfaces() ?

-                withSettings().extraInterfaces(returnTypeGenericMetadata.rawExtraInterfaces())

-                : withSettings();

-

-        return propagateSerializationSettings(mockSettings, parentMockSettings)

-                .defaultAnswer(returnsDeepStubsAnswerUsing(returnTypeGenericMetadata));

-    }

-

-    private MockSettings propagateSerializationSettings(MockSettings mockSettings, MockCreationSettings parentMockSettings) {

-        return mockSettings.serializable(parentMockSettings.getSerializableMode());

-    }

-

-    private ReturnsDeepStubs returnsDeepStubsAnswerUsing(final GenericMetadataSupport returnTypeGenericMetadata) {

-        return new ReturnsDeepStubsSerializationFallback(returnTypeGenericMetadata);

-    }

-

-    private Object recordDeepStubAnswer(final Object mock, InvocationContainerImpl container) throws Throwable {

-        container.addAnswer(new DeeplyStubbedAnswer(mock), false);

-        return mock;

-    }

-

-    protected GenericMetadataSupport actualParameterizedType(Object mock) {

-        CreationSettings mockSettings = (CreationSettings) new MockUtil().getMockHandler(mock).getMockSettings();

-        return GenericMetadataSupport.inferFrom(mockSettings.getTypeToMock());

-    }

-

-

-    private static class ReturnsDeepStubsSerializationFallback extends ReturnsDeepStubs implements Serializable {

-        @SuppressWarnings("serial") // not gonna be serialized

-        private final GenericMetadataSupport returnTypeGenericMetadata;

-

-        public ReturnsDeepStubsSerializationFallback(GenericMetadataSupport returnTypeGenericMetadata) {

-            this.returnTypeGenericMetadata = returnTypeGenericMetadata;

-        }

-

-        @Override

-        protected GenericMetadataSupport actualParameterizedType(Object mock) {

-            return returnTypeGenericMetadata;

-        }

-        private Object writeReplace() throws IOException {

-            return Mockito.RETURNS_DEEP_STUBS;

-        }

-    }

-

-

-    private static class DeeplyStubbedAnswer implements Answer<Object>, Serializable {

-        @SuppressWarnings("serial") // serialization will fail with a nice message if mock not serializable

-        private final Object mock;

-

-        DeeplyStubbedAnswer(Object mock) {

-            this.mock = mock;

-        }

-        public Object answer(InvocationOnMock invocation) throws Throwable {

-            return mock;

-        }

-    }

-

-

-    private static MockitoCore mockitoCore() {

-        return LazyHolder.MOCKITO_CORE;

-    }

-

-    private static ReturnsEmptyValues delegate() {

-        return LazyHolder.DELEGATE;

-    }

-

-    private static class LazyHolder {

-        private static final MockitoCore MOCKITO_CORE = new MockitoCore();

-        private static final ReturnsEmptyValues DELEGATE = new ReturnsEmptyValues();

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.stubbing.InvocationContainerImpl;
+import org.mockito.internal.stubbing.StubbedInvocationMatcher;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.GenericMetadataSupport;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * Returning deep stub implementation.
+ *
+ * Will return previously created mock if the invocation matches.
+ *
+ * <p>Supports nested generic information, with this answer you can write code like this :
+ *
+ * <pre class="code"><code class="java">
+ *     interface GenericsNest&lt;K extends Comparable&lt;K&gt; & Cloneable&gt; extends Map&lt;K, Set&lt;Number&gt;&gt; {}
+ *
+ *     GenericsNest&lt;?&gt; mock = mock(GenericsNest.class, new ReturnsGenericDeepStubs());
+ *     Number number = mock.entrySet().iterator().next().getValue().iterator().next();
+ * </code></pre>
+ * </p>
+ *
+ * @see org.mockito.Mockito#RETURNS_DEEP_STUBS
+ * @see org.mockito.Answers#RETURNS_DEEP_STUBS
+ */
+public class ReturnsDeepStubs implements Answer<Object>, Serializable {
+
+    private static final long serialVersionUID = -7105341425736035847L;
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        GenericMetadataSupport returnTypeGenericMetadata =
+                actualParameterizedType(invocation.getMock()).resolveGenericReturnType(invocation.getMethod());
+
+        Class<?> rawType = returnTypeGenericMetadata.rawType();
+        if (!mockitoCore().isTypeMockable(rawType)) {
+            return delegate().returnValueFor(rawType);
+        }
+
+        return deepStub(invocation, returnTypeGenericMetadata);
+    }
+
+    private Object deepStub(InvocationOnMock invocation, GenericMetadataSupport returnTypeGenericMetadata) throws Throwable {
+        InternalMockHandler<Object> handler = MockUtil.getMockHandler(invocation.getMock());
+        InvocationContainerImpl container = (InvocationContainerImpl) handler.getInvocationContainer();
+
+        // matches invocation for verification
+        for (StubbedInvocationMatcher stubbedInvocationMatcher : container.getStubbedInvocations()) {
+            if (container.getInvocationForStubbing().matches(stubbedInvocationMatcher.getInvocation())) {
+                return stubbedInvocationMatcher.answer(invocation);
+            }
+        }
+
+        // record deep stub answer
+        StubbedInvocationMatcher stubbing = recordDeepStubAnswer(
+                newDeepStubMock(returnTypeGenericMetadata, invocation.getMock()),
+                container
+        );
+
+        // deep stubbing creates a stubbing and immediately uses it
+        // so the stubbing is actually used by the same invocation
+        stubbing.markStubUsed(stubbing.getInvocation());
+
+        return stubbing.answer(invocation);
+    }
+
+    /**
+     * Creates a mock using the Generics Metadata.
+     *
+     * <li>Finally as we want to mock the actual type, but we want to pass along the contextual generics meta-data
+     * that was resolved for the current return type, for this to happen we associate to the mock an new instance of
+     * {@link ReturnsDeepStubs} answer in which we will store the returned type generic metadata.
+     *
+     * @param returnTypeGenericMetadata The metadata to use to create the new mock.
+     * @param parentMock The parent of the current deep stub mock.
+     * @return The mock
+     */
+    private Object newDeepStubMock(GenericMetadataSupport returnTypeGenericMetadata, Object parentMock) {
+        MockCreationSettings parentMockSettings = MockUtil.getMockSettings(parentMock);
+        return mockitoCore().mock(
+                returnTypeGenericMetadata.rawType(),
+                withSettingsUsing(returnTypeGenericMetadata, parentMockSettings)
+        );
+    }
+
+    private MockSettings withSettingsUsing(GenericMetadataSupport returnTypeGenericMetadata, MockCreationSettings parentMockSettings) {
+        MockSettings mockSettings = returnTypeGenericMetadata.hasRawExtraInterfaces() ?
+                withSettings().extraInterfaces(returnTypeGenericMetadata.rawExtraInterfaces())
+                : withSettings();
+
+        return propagateSerializationSettings(mockSettings, parentMockSettings)
+                .defaultAnswer(returnsDeepStubsAnswerUsing(returnTypeGenericMetadata));
+    }
+
+    private MockSettings propagateSerializationSettings(MockSettings mockSettings, MockCreationSettings parentMockSettings) {
+        return mockSettings.serializable(parentMockSettings.getSerializableMode());
+    }
+
+    private ReturnsDeepStubs returnsDeepStubsAnswerUsing(final GenericMetadataSupport returnTypeGenericMetadata) {
+        return new ReturnsDeepStubsSerializationFallback(returnTypeGenericMetadata);
+    }
+
+    private StubbedInvocationMatcher recordDeepStubAnswer(final Object mock, InvocationContainerImpl container) {
+        DeeplyStubbedAnswer answer = new DeeplyStubbedAnswer(mock);
+        return container.addAnswer(answer, false);
+    }
+
+    protected GenericMetadataSupport actualParameterizedType(Object mock) {
+        CreationSettings mockSettings = (CreationSettings) MockUtil.getMockHandler(mock).getMockSettings();
+        return GenericMetadataSupport.inferFrom(mockSettings.getTypeToMock());
+    }
+
+
+    private static class ReturnsDeepStubsSerializationFallback extends ReturnsDeepStubs implements Serializable {
+        @SuppressWarnings("serial") // not gonna be serialized
+        private final GenericMetadataSupport returnTypeGenericMetadata;
+
+        public ReturnsDeepStubsSerializationFallback(GenericMetadataSupport returnTypeGenericMetadata) {
+            this.returnTypeGenericMetadata = returnTypeGenericMetadata;
+        }
+
+        @Override
+        protected GenericMetadataSupport actualParameterizedType(Object mock) {
+            return returnTypeGenericMetadata;
+        }
+        private Object writeReplace() throws IOException {
+            return Mockito.RETURNS_DEEP_STUBS;
+        }
+    }
+
+
+    private static class DeeplyStubbedAnswer implements Answer<Object>, Serializable {
+        @SuppressWarnings("serial") // serialization will fail with a nice message if mock not serializable
+        private final Object mock;
+
+        DeeplyStubbedAnswer(Object mock) {
+            this.mock = mock;
+        }
+        public Object answer(InvocationOnMock invocation) throws Throwable {
+            return mock;
+        }
+    }
+
+
+    private static MockitoCore mockitoCore() {
+        return LazyHolder.MOCKITO_CORE;
+    }
+
+    private static ReturnsEmptyValues delegate() {
+        return LazyHolder.DELEGATE;
+    }
+
+    private static class LazyHolder {
+        private static final MockitoCore MOCKITO_CORE = new MockitoCore();
+        private static final ReturnsEmptyValues DELEGATE = new ReturnsEmptyValues();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java
index d19fcda..2216cca 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java
@@ -1,10 +1,10 @@
 /*
- * Copyright (c) 2007 Mockito contributors
+ * Copyright (c) 2016 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-
 package org.mockito.internal.stubbing.defaultanswers;
 
+import org.mockito.internal.util.JavaEightUtil;
 import org.mockito.internal.util.MockUtil;
 import org.mockito.internal.util.ObjectMethodsGuru;
 import org.mockito.internal.util.Primitives;
@@ -12,79 +12,76 @@
 import org.mockito.mock.MockName;
 import org.mockito.stubbing.Answer;
 
+import static org.mockito.internal.util.ObjectMethodsGuru.isCompareToMethod;
+import static org.mockito.internal.util.ObjectMethodsGuru.isToStringMethod;
+
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TreeMap;
-import java.util.TreeSet;
+import java.util.*;
 
 /**
  * Default answer of every Mockito mock.
  * <ul>
  * <li>
- *  Returns appropriate primitive for primitive-returning methods
+ * Returns appropriate primitive for primitive-returning methods
  * </li>
  * <li>
- *  Returns consistent values for primitive wrapper classes (e.g. int-returning method retuns 0 <b>and</b> Integer-returning method returns 0, too)
+ * Returns consistent values for primitive wrapper classes (e.g. int-returning method returns 0 <b>and</b> Integer-returning method returns 0, too)
  * </li>
  * <li>
- *  Returns empty collection for collection-returning methods (works for most commonly used collection types)
+ * Returns empty collection for collection-returning methods (works for most commonly used collection types)
  * </li>
  * <li>
- *  Returns description of mock for toString() method
+ * Returns description of mock for toString() method
  * </li>
  * <li>
- *  Returns zero if references are equals otherwise non-zero for Comparable#compareTo(T other) method (see issue 184)
+ * Returns zero if references are equals otherwise non-zero for Comparable#compareTo(T other) method (see issue 184)
  * </li>
  * <li>
- *  Returns null for everything else
+ * Returns an {@code java.util.Optional#empty() empty Optional} for Optional. Similarly for primitive optional variants.
+ * </li>
+ * <li>
+ * Returns an {@code java.util.stream.Stream#empty() empty Stream} for Stream. Similarly for primitive stream variants.
+ * </li>
+ * <li>
+ * Returns null for everything else
  * </li>
  * </ul>
  */
 public class ReturnsEmptyValues implements Answer<Object>, Serializable {
-    
+
     private static final long serialVersionUID = 1998191268711234347L;
-    ObjectMethodsGuru methodsGuru = new ObjectMethodsGuru();
-    MockUtil mockUtil = new MockUtil();
+
 
     /* (non-Javadoc)
      * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
      */
     public Object answer(InvocationOnMock invocation) {
-        if (methodsGuru.isToString(invocation.getMethod())) {
+        if (isToStringMethod(invocation.getMethod())) {
             Object mock = invocation.getMock();
-            MockName name = mockUtil.getMockName(mock);
+            MockName name = MockUtil.getMockName(mock);
             if (name.isDefault()) {
-                return "Mock for " + mockUtil.getMockSettings(mock).getTypeToMock().getSimpleName() + ", hashCode: " + mock.hashCode();
+                return "Mock for " + MockUtil.getMockSettings(mock).getTypeToMock().getSimpleName() + ", hashCode: " + mock.hashCode();
             } else {
                 return name.toString();
             }
-        } else if (methodsGuru.isCompareToMethod(invocation.getMethod())) {
+        } else if (isCompareToMethod(invocation.getMethod())) {
             //see issue 184.
             //mocks by default should return 0 if references are the same, otherwise some other value because they are not the same. Hence we return 1 (anything but 0 is good).
             //Only for compareTo() method by the Comparable interface
-            return invocation.getMock() == invocation.getArguments()[0] ? 0 : 1;
+            return invocation.getMock() == invocation.getArgument(0) ? 0 : 1;
         }
-        
+
         Class<?> returnType = invocation.getMethod().getReturnType();
         return returnValueFor(returnType);
     }
-    
+
     Object returnValueFor(Class<?> type) {
         if (Primitives.isPrimitiveOrWrapper(type)) {
-            return Primitives.defaultValueForPrimitiveOrWrapper(type);
-        //new instances are used instead of Collections.emptyList(), etc.
-        //to avoid UnsupportedOperationException if code under test modifies returned collection
+            return Primitives.defaultValue(type);
+            //new instances are used instead of Collections.emptyList(), etc.
+            //to avoid UnsupportedOperationException if code under test modifies returned collection
+        } else if (type == Iterable.class) {
+            return new ArrayList<Object>(0);
         } else if (type == Collection.class) {
             return new LinkedList<Object>();
         } else if (type == Set.class) {
@@ -113,11 +110,25 @@
             return new TreeMap<Object, Object>();
         } else if (type == LinkedHashMap.class) {
             return new LinkedHashMap<Object, Object>();
+        } else if ("java.util.Optional".equals(type.getName())) {
+            return JavaEightUtil.emptyOptional();
+        } else if ("java.util.OptionalDouble".equals(type.getName())) {
+            return JavaEightUtil.emptyOptionalDouble();
+        } else if ("java.util.OptionalInt".equals(type.getName())) {
+            return JavaEightUtil.emptyOptionalInt();
+        } else if ("java.util.OptionalLong".equals(type.getName())) {
+            return JavaEightUtil.emptyOptionalLong();
+        } else if ("java.util.stream.Stream".equals(type.getName())) {
+            return JavaEightUtil.emptyStream();
+        } else if ("java.util.stream.DoubleStream".equals(type.getName())) {
+            return JavaEightUtil.emptyDoubleStream();
+        } else if ("java.util.stream.IntStream".equals(type.getName())) {
+            return JavaEightUtil.emptyIntStream();
+        } else if ("java.util.stream.LongStream".equals(type.getName())) {
+            return JavaEightUtil.emptyLongStream();
         }
-        // TODO return empty Iterable ; see issue 175
 
         //Let's not care about the rest of collections.
         return null;
     }
-
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java
index e6a585f..302e4df 100755
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java
@@ -1,36 +1,36 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.stubbing.defaultanswers;

-

-import org.mockito.internal.MockitoCore;

-import org.mockito.internal.creation.MockSettingsImpl;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-import java.io.Serializable;

-

-public class ReturnsMocks implements Answer<Object>, Serializable {

-    

-    private static final long serialVersionUID = -6755257986994634579L;

-    private final MockitoCore mockitoCore = new MockitoCore();

-    private final Answer<Object> delegate = new ReturnsMoreEmptyValues();

-    

-    public Object answer(InvocationOnMock invocation) throws Throwable {

-        Object ret = delegate.answer(invocation);

-        if (ret != null) {

-            return ret;

-        }

-            

-        return returnValueFor(invocation.getMethod().getReturnType());

-    }

-

-    Object returnValueFor(Class<?> clazz) {

-        if (!mockitoCore.isTypeMockable(clazz)) {

-            return null;

-        }

-        

-        return mockitoCore.mock(clazz, new MockSettingsImpl().defaultAnswer(this));

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+public class ReturnsMocks implements Answer<Object>, Serializable {
+
+    private static final long serialVersionUID = -6755257986994634579L;
+    private final MockitoCore mockitoCore = new MockitoCore();
+    private final Answer<Object> delegate = new ReturnsMoreEmptyValues();
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        Object ret = delegate.answer(invocation);
+        if (ret != null) {
+            return ret;
+        }
+
+        return returnValueFor(invocation.getMethod().getReturnType());
+    }
+
+    Object returnValueFor(Class<?> clazz) {
+        if (!mockitoCore.isTypeMockable(clazz)) {
+            return null;
+        }
+
+        return mockitoCore.mock(clazz, new MockSettingsImpl().defaultAnswer(this));
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java
index 39c0247..d035919 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java
@@ -5,19 +5,18 @@
 
 package org.mockito.internal.stubbing.defaultanswers;
 
+import java.io.Serializable;
+import java.lang.reflect.Array;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import java.io.Serializable;
-import java.lang.reflect.Array;
-
 /**
- * It's likely this implementation will be used by default by every Mockito 2.0 mock.
+ * It's likely this implementation will be used by default by every Mockito 3.0.0 mock.
  * <p>
  * Currently <b>used only</b> by {@link Mockito#RETURNS_SMART_NULLS}
  * <p>
- * Current version of Mockito mocks by deafult use {@link ReturnsEmptyValues}  
+ * Current version of Mockito mocks by deafult use {@link ReturnsEmptyValues}
  * <ul>
  * <li>
  *  Returns appropriate primitive for primitive-returning methods
@@ -46,10 +45,10 @@
  * </ul>
  */
 public class ReturnsMoreEmptyValues implements Answer<Object>, Serializable {
-    
+
     private static final long serialVersionUID = -2816745041482698471L;
     private final Answer<Object> delegate = new ReturnsEmptyValues();
-    
+
     /* (non-Javadoc)
      * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
      */
@@ -62,14 +61,14 @@
         Class<?> returnType = invocation.getMethod().getReturnType();
         return returnValueFor(returnType);
     }
-    
+
     Object returnValueFor(Class<?> type) {
         if (type == String.class) {
             return "";
         }  else if (type.isArray()) {
-            Class<?> componenetType = type.getComponentType();
-            return Array.newInstance(componenetType, 0);
+            Class<?> componentType = type.getComponentType();
+            return Array.newInstance(componentType, 0);
         }
         return null;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java
index c2462b0..7487e89 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java
@@ -2,73 +2,73 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.stubbing.defaultanswers;

-

-import java.io.Serializable;

-import java.lang.reflect.Modifier;

-

-import org.mockito.Mockito;

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.debugging.LocationImpl;

-import org.mockito.invocation.Location;

-import org.mockito.internal.util.ObjectMethodsGuru;

-import org.mockito.invocation.InvocationOnMock;

-import org.mockito.stubbing.Answer;

-

-/**

- * Optional Answer that can be used with

- * {@link Mockito#mock(Class, Answer)}

- * <p>

- * This implementation can be helpful when working with legacy code. Unstubbed

- * methods often return null. If your code uses the object returned by an

- * unstubbed call you get a NullPointerException. This implementation of

- * Answer returns SmartNulls instead of nulls.

- * SmartNull gives nicer exception message than NPE because it points out the

- * line where unstubbed method was called. You just click on the stack trace.

- * <p>

- * ReturnsSmartNulls first tries to return ordinary return values (see

- * {@link ReturnsMoreEmptyValues}) then it tries to return SmartNull. If the

- * return type is not mockable (e.g. final) then ordinary null is returned.

- * <p>

- * ReturnsSmartNulls will be probably the default return values strategy in

- * Mockito 2.0

- */

-public class ReturnsSmartNulls implements Answer<Object>, Serializable {

-

-    private static final long serialVersionUID = 7618312406617949441L;

-

-    private final Answer<Object> delegate = new ReturnsMoreEmptyValues();

-

-    public Object answer(final InvocationOnMock invocation) throws Throwable {

-        Object defaultReturnValue = delegate.answer(invocation);

-        if (defaultReturnValue != null) {

-            return defaultReturnValue;

-        }

-        Class<?> type = invocation.getMethod().getReturnType();

-        if (!type.isPrimitive() && !Modifier.isFinal(type.getModifiers())) {

-            final Location location = new LocationImpl();

-            return Mockito.mock(type, new ThrowsSmartNullPointer(invocation, location));

-        }

-        return null;

-    }

-

-    private static class ThrowsSmartNullPointer implements Answer {

-        private final InvocationOnMock unstubbedInvocation;

-        private final Location location;

-

-        public ThrowsSmartNullPointer(InvocationOnMock unstubbedInvocation, Location location) {

-            this.unstubbedInvocation = unstubbedInvocation;

-            this.location = location;

-        }

-

-        public Object answer(InvocationOnMock currentInvocation) throws Throwable {

-            if (new ObjectMethodsGuru().isToString(currentInvocation.getMethod())) {

-                return "SmartNull returned by this unstubbed method call on a mock:\n" +

-                        unstubbedInvocation.toString();

-            }

-

-            new Reporter().smartNullPointerException(unstubbedInvocation.toString(), location);

-            return null;

-        }

-    }

-}

+package org.mockito.internal.stubbing.defaultanswers;
+
+import static org.mockito.internal.exceptions.Reporter.smartNullPointerException;
+import static org.mockito.internal.util.ObjectMethodsGuru.isToStringMethod;
+
+import java.io.Serializable;
+import java.lang.reflect.Modifier;
+
+import org.mockito.Mockito;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.invocation.Location;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Optional Answer that can be used with
+ * {@link Mockito#mock(Class, Answer)}
+ * <p>
+ * This implementation can be helpful when working with legacy code. Unstubbed
+ * methods often return null. If your code uses the object returned by an
+ * unstubbed call you get a NullPointerException. This implementation of
+ * Answer returns SmartNulls instead of nulls.
+ * SmartNull gives nicer exception message than NPE because it points out the
+ * line where unstubbed method was called. You just click on the stack trace.
+ * <p>
+ * ReturnsSmartNulls first tries to return ordinary return values (see
+ * {@link ReturnsMoreEmptyValues}) then it tries to return SmartNull. If the
+ * return type is not mockable (e.g. final) then ordinary null is returned.
+ * <p>
+ * ReturnsSmartNulls will be probably the default return values strategy in
+ * Mockito 2.1.0
+ */
+public class ReturnsSmartNulls implements Answer<Object>, Serializable {
+
+    private static final long serialVersionUID = 7618312406617949441L;
+
+    private final Answer<Object> delegate = new ReturnsMoreEmptyValues();
+
+    public Object answer(final InvocationOnMock invocation) throws Throwable {
+        Object defaultReturnValue = delegate.answer(invocation);
+        if (defaultReturnValue != null) {
+            return defaultReturnValue;
+        }
+        Class<?> type = invocation.getMethod().getReturnType();
+        if (!type.isPrimitive() && !Modifier.isFinal(type.getModifiers())) {
+            final Location location = new LocationImpl();
+            return Mockito.mock(type, new ThrowsSmartNullPointer(invocation, location));
+        }
+        return null;
+    }
+
+    private static class ThrowsSmartNullPointer implements Answer {
+        private final InvocationOnMock unstubbedInvocation;
+        private final Location location;
+
+        public ThrowsSmartNullPointer(InvocationOnMock unstubbedInvocation, Location location) {
+            this.unstubbedInvocation = unstubbedInvocation;
+            this.location = location;
+        }
+
+        public Object answer(InvocationOnMock currentInvocation) throws Throwable {
+            if (isToStringMethod(currentInvocation.getMethod())) {
+                return "SmartNull returned by this unstubbed method call on a mock:\n" +
+                        unstubbedInvocation.toString();
+            }
+
+            throw smartNullPointerException(unstubbedInvocation.toString(), location);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/TriesToReturnSelf.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/TriesToReturnSelf.java
new file mode 100644
index 0000000..27cf121
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/TriesToReturnSelf.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+public class TriesToReturnSelf implements Answer<Object>, Serializable{
+
+    private final ReturnsEmptyValues defaultReturn = new ReturnsEmptyValues();
+
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        Class<?> methodReturnType = invocation.getMethod().getReturnType();
+        Object mock = invocation.getMock();
+        Class<?> mockType = MockUtil.getMockHandler(mock).getMockSettings().getTypeToMock();
+
+        if (methodReturnType.isAssignableFrom(mockType)) {
+            return invocation.getMock();
+        }
+
+        return defaultReturn.returnValueFor(methodReturnType);
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/package-info.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/package-info.java
new file mode 100644
index 0000000..923133a
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Implementations of default Answers.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/package.html b/src/main/java/org/mockito/internal/stubbing/defaultanswers/package.html
deleted file mode 100644
index 1587715..0000000
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Implementations of ReturnValues
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/stubbing/package-info.java b/src/main/java/org/mockito/internal/stubbing/package-info.java
new file mode 100644
index 0000000..57c8138
--- /dev/null
+++ b/src/main/java/org/mockito/internal/stubbing/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Stubbing logic.
+ */
+package org.mockito.internal.stubbing;
diff --git a/src/main/java/org/mockito/internal/stubbing/package.html b/src/main/java/org/mockito/internal/stubbing/package.html
deleted file mode 100644
index 4f6d4e8..0000000
--- a/src/main/java/org/mockito/internal/stubbing/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Stubbing logic.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/util/Checks.java b/src/main/java/org/mockito/internal/util/Checks.java
index 00ed8a8..9731dbe 100644
--- a/src/main/java/org/mockito/internal/util/Checks.java
+++ b/src/main/java/org/mockito/internal/util/Checks.java
@@ -12,12 +12,12 @@
 
     public static <T> T checkNotNull(T value, String checkedValue) {
         if(value == null) {
-            throw new NullPointerException(checkedValue + " should not be null");
+            throw new IllegalArgumentException(checkedValue + " should not be null");
         }
         return value;
     }
 
-    public static <T extends Iterable> T checkItemsNotNull(T iterable, String checkedIterable) {
+    public static <T extends Iterable<?>> T checkItemsNotNull(T iterable, String checkedIterable) {
         checkNotNull(iterable, checkedIterable);
         for (Object item : iterable) {
             checkNotNull(item, "item in " + checkedIterable);
diff --git a/src/main/java/org/mockito/internal/util/ConsoleMockitoLogger.java b/src/main/java/org/mockito/internal/util/ConsoleMockitoLogger.java
index 80cac5c..d8df8eb 100644
--- a/src/main/java/org/mockito/internal/util/ConsoleMockitoLogger.java
+++ b/src/main/java/org/mockito/internal/util/ConsoleMockitoLogger.java
@@ -1,15 +1,15 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util;

-

-public class ConsoleMockitoLogger implements MockitoLogger {

-

-    /* (non-Javadoc)

-     * @see org.mockito.internal.util.Logger#print(java.lang.Object)

-     */

-    public void log(Object what) {

-        System.out.println(what);

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+public class ConsoleMockitoLogger implements MockitoLogger {
+
+    /* (non-Javadoc)
+     * @see org.mockito.internal.util.Logger#print(java.lang.Object)
+     */
+    public void log(Object what) {
+        System.out.println(what);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/Decamelizer.java b/src/main/java/org/mockito/internal/util/Decamelizer.java
index 9bc34be..8875389 100644
--- a/src/main/java/org/mockito/internal/util/Decamelizer.java
+++ b/src/main/java/org/mockito/internal/util/Decamelizer.java
@@ -8,21 +8,22 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+//TODO SF move to matchers.text
 public class Decamelizer {
 
 private static final Pattern CAPS = Pattern.compile("([A-Z\\d][^A-Z\\d]*)");
-    
+
     public static String decamelizeMatcher(String className) {
         if (className.length() == 0) {
             return "<custom argument matcher>";
         }
-        
+
         String decamelized = decamelizeClassName(className);
-        
+
         if (decamelized.length() == 0) {
             return "<" + className + ">";
         }
-        
+
         return "<" + decamelized + ">";
     }
 
diff --git a/src/main/java/org/mockito/internal/util/DefaultMockingDetails.java b/src/main/java/org/mockito/internal/util/DefaultMockingDetails.java
index e361c6e..7114a46 100644
--- a/src/main/java/org/mockito/internal/util/DefaultMockingDetails.java
+++ b/src/main/java/org/mockito/internal/util/DefaultMockingDetails.java
@@ -1,45 +1,81 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util;

-

-import org.mockito.MockingDetails;

-import org.mockito.invocation.Invocation;

-

-import java.util.Collection;

-

-/**

- * Class to inspect any object, and identify whether a particular object is either a mock or a spy.  This is

- * a wrapper for {@link org.mockito.internal.util.MockUtil}.

- */

-public class DefaultMockingDetails implements MockingDetails {

-

-    private final Object toInspect;

-    private final MockUtil delegate;

-

-    public DefaultMockingDetails(Object toInspect, MockUtil delegate){

-        this.toInspect = toInspect;

-        this.delegate = delegate;

-    }

-    /**

-     * Find out whether the object is a mock.

-     * @return true if the object is a mock or a spy.

-     */

-    public boolean isMock(){

-        return delegate.isMock( toInspect );

-    }

-

-    /**

-     * Find out whether the object is a spy.

-     * @return true if the object is a spy.

-     */

-    public boolean isSpy(){

-        return delegate.isSpy( toInspect );

-    }

-    

-    public Collection<Invocation> getInvocations() {

-    	return delegate.getMockHandler(toInspect).getInvocationContainer().getInvocations();

-    }

-}

-

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.MockingDetails;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.debugging.InvocationsPrinter;
+import org.mockito.stubbing.Stubbing;
+import org.mockito.internal.stubbing.StubbingComparator;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.TreeSet;
+
+import static org.mockito.internal.util.MockUtil.getMockHandler;
+
+/**
+ * Class to inspect any object, and identify whether a particular object is either a mock or a spy.  This is
+ * a wrapper for {@link org.mockito.internal.util.MockUtil}.
+ */
+public class DefaultMockingDetails implements MockingDetails {
+
+    private final Object toInspect;
+
+    public DefaultMockingDetails(Object toInspect){
+        this.toInspect = toInspect;
+    }
+
+    @Override
+    public boolean isMock(){
+        return MockUtil.isMock(toInspect);
+    }
+
+    @Override
+    public boolean isSpy(){
+        return MockUtil.isSpy(toInspect);
+    }
+
+    @Override
+    public Collection<Invocation> getInvocations() {
+        return mockHandler().getInvocationContainer().getInvocations();
+    }
+
+    @Override
+    public MockCreationSettings<?> getMockCreationSettings() {
+        return mockHandler().getMockSettings();
+    }
+
+    @Override
+    public Collection<Stubbing> getStubbings() {
+        List<? extends Stubbing> stubbings = mockHandler().getInvocationContainer().getStubbedInvocations();
+        TreeSet<Stubbing> out = new TreeSet<Stubbing>(new StubbingComparator());
+        out.addAll(stubbings);
+        return out;
+    }
+
+    @Override
+    public String printInvocations() {
+        assertGoodMock();
+        return new InvocationsPrinter().printInvocations(toInspect);
+    }
+
+    private InternalMockHandler<Object> mockHandler() {
+        assertGoodMock();
+        return getMockHandler(toInspect);
+    }
+
+    private void assertGoodMock() {
+        if (toInspect == null) {
+            throw new NotAMockException("Argument passed to Mockito.mockingDetails() should be a mock, but is null!");
+        } else if (!isMock()) {
+            throw new NotAMockException("Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of " + toInspect.getClass() + "!");
+        }
+    }
+}
+
diff --git a/src/main/java/org/mockito/internal/util/JavaEightUtil.java b/src/main/java/org/mockito/internal/util/JavaEightUtil.java
new file mode 100644
index 0000000..80ac635
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/JavaEightUtil.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.internal.creation.instance.InstantiationException;
+
+import java.lang.reflect.Method;
+
+/**
+ * Helper class to work with features that were introduced in Java versions after 1.5.
+ * This class uses reflection in most places to avoid coupling with a newer JDK.
+ */
+public final class JavaEightUtil {
+
+    // No need for volatile, these optionals are already safe singletons.
+    private static Object emptyOptional;
+    private static Object emptyOptionalDouble;
+    private static Object emptyOptionalInt;
+    private static Object emptyOptionalLong;
+
+    private JavaEightUtil() {
+        // utility class
+    }
+
+    /**
+     * Creates an empty Optional using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty Optional.
+     */
+    public static Object emptyOptional() {
+        // no need for double-checked locking
+        if (emptyOptional != null) {
+            return emptyOptional;
+        }
+
+        return emptyOptional = invokeNullaryFactoryMethod("java.util.Optional", "empty");
+    }
+
+
+    /**
+     * Creates an empty OptionalDouble using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty OptionalDouble.
+     */
+    public static Object emptyOptionalDouble() {
+        // no need for double-checked locking
+        if (emptyOptionalDouble != null) {
+            return emptyOptionalDouble;
+        }
+
+        return emptyOptionalDouble = invokeNullaryFactoryMethod("java.util.OptionalDouble", "empty");
+    }
+
+    /**
+     * Creates an empty OptionalInt using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty OptionalInt.
+     */
+    public static Object emptyOptionalInt() {
+        // no need for double-checked locking
+        if (emptyOptionalInt != null) {
+            return emptyOptionalInt;
+        }
+
+        return emptyOptionalInt = invokeNullaryFactoryMethod("java.util.OptionalInt", "empty");
+    }
+
+    /**
+     * Creates an empty OptionalLong using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty OptionalLong.
+     */
+    public static Object emptyOptionalLong() {
+        // no need for double-checked locking
+        if (emptyOptionalLong != null) {
+            return emptyOptionalLong;
+        }
+
+        return emptyOptionalLong = invokeNullaryFactoryMethod("java.util.OptionalLong", "empty");
+    }
+
+    /**
+     * Creates an empty Stream using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty Stream.
+     */
+    public static Object emptyStream() {
+        // note: the empty stream can not be stored as a singleton.
+        return invokeNullaryFactoryMethod("java.util.stream.Stream", "empty");
+    }
+
+    /**
+     * Creates an empty DoubleStream using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty DoubleStream.
+     */
+    public static Object emptyDoubleStream() {
+        // note: the empty stream can not be stored as a singleton.
+        return invokeNullaryFactoryMethod("java.util.stream.DoubleStream", "empty");
+    }
+
+    /**
+     * Creates an empty IntStream using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty IntStream.
+     */
+    public static Object emptyIntStream() {
+        // note: the empty stream can not be stored as a singleton.
+        return invokeNullaryFactoryMethod("java.util.stream.IntStream", "empty");
+    }
+
+    /**
+     * Creates an empty LongStream using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @return an empty LongStream.
+     */
+    public static Object emptyLongStream() {
+        // note: the empty stream can not be stored as a singleton.
+        return invokeNullaryFactoryMethod("java.util.stream.LongStream", "empty");
+    }
+
+    /**
+     * Invokes a nullary static factory method using reflection to stay backwards-compatible with older JDKs.
+     *
+     * @param fqcn The fully qualified class name of the type to be produced.
+     * @param methodName The name of the factory method.
+     * @return the object produced.
+     */
+    private static Object invokeNullaryFactoryMethod(final String fqcn, final String methodName) {
+        try {
+            final Class<?> type = Class.forName(fqcn);
+            final Method method = type.getMethod(methodName);
+
+            return method.invoke(null);
+            // any exception is really unexpected since the type name has
+            // already been verified
+        } catch (final Exception e) {
+            throw new InstantiationException(
+                    String.format("Could not create %s#%s(): %s", fqcn, methodName, e), e);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/MockCreationValidator.java b/src/main/java/org/mockito/internal/util/MockCreationValidator.java
index 35d99d9..5dba346 100644
--- a/src/main/java/org/mockito/internal/util/MockCreationValidator.java
+++ b/src/main/java/org/mockito/internal/util/MockCreationValidator.java
@@ -1,73 +1,63 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.util.reflection.Constructors;

-import org.mockito.mock.SerializableMode;

-

-import java.io.Serializable;

-import java.util.Collection;

-

-@SuppressWarnings("unchecked")

-public class MockCreationValidator {

-

-    private final MockUtil mockUtil = new MockUtil();

-

-    public void validateType(Class classToMock) {

-        if (!mockUtil.isTypeMockable(classToMock)) {

-            new Reporter().cannotMockFinalClass(classToMock);

-        }

-    }

-

-    public void validateExtraInterfaces(Class classToMock, Collection<Class> extraInterfaces) {

-        if (extraInterfaces == null) {

-            return;

-        }

-

-        for (Class i : extraInterfaces) {

-            if (classToMock == i) {

-                new Reporter().extraInterfacesCannotContainMockedType(classToMock);

-            }

-        }

-    }

-

-    public void validateMockedType(Class classToMock, Object spiedInstance) {

-        if (classToMock == null || spiedInstance == null) {

-            return;

-        }

-        if (!classToMock.equals(spiedInstance.getClass())) {

-            new Reporter().mockedTypeIsInconsistentWithSpiedInstanceType(classToMock, spiedInstance);

-        }

-    }

-

-    public void validateDelegatedInstance(Class classToMock, Object delegatedInstance) {

-        if (classToMock == null || delegatedInstance == null) {

-            return;

-        }

-        if (delegatedInstance.getClass().isAssignableFrom(classToMock)) {

-            new Reporter().mockedTypeIsInconsistentWithDelegatedInstanceType(classToMock, delegatedInstance);

-        }

-    }

-

-    public void validateSerializable(Class classToMock, boolean serializable) {

-        // We can't catch all the errors with this piece of code

-        // Having a **superclass that do not implements Serializable** might fail as well when serialized

-        // Though it might prevent issues when mockito is mocking a class without superclass.

-        if(serializable

-                && !classToMock.isInterface()

-                && !(Serializable.class.isAssignableFrom(classToMock))

-                && Constructors.noArgConstructorOf(classToMock) == null

-                ) {

-            new Reporter().serializableWontWorkForObjectsThatDontImplementSerializable(classToMock);

-        }

-    }

-

-    public void validateConstructorUse(boolean usingConstructor, SerializableMode mode) {

-        if (usingConstructor && mode == SerializableMode.ACROSS_CLASSLOADERS) {

-            new Reporter().usingConstructorWithFancySerializable(mode);

-        }

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import static org.mockito.internal.exceptions.Reporter.cannotMockClass;
+import static org.mockito.internal.exceptions.Reporter.extraInterfacesCannotContainMockedType;
+import static org.mockito.internal.exceptions.Reporter.mockedTypeIsInconsistentWithDelegatedInstanceType;
+import static org.mockito.internal.exceptions.Reporter.mockedTypeIsInconsistentWithSpiedInstanceType;
+import static org.mockito.internal.exceptions.Reporter.usingConstructorWithFancySerializable;
+
+import java.util.Collection;
+
+import org.mockito.mock.SerializableMode;
+import org.mockito.plugins.MockMaker.TypeMockability;
+
+@SuppressWarnings("unchecked")
+public class MockCreationValidator {
+
+    public void validateType(Class<?> classToMock) {
+        TypeMockability typeMockability = MockUtil.typeMockabilityOf(classToMock);
+        if (!typeMockability.mockable()) {
+            throw cannotMockClass(classToMock, typeMockability.nonMockableReason());
+        }
+    }
+
+    public void validateExtraInterfaces(Class<?> classToMock, Collection<Class<?>> extraInterfaces) {
+        if (extraInterfaces == null) {
+            return;
+        }
+
+        for (Class<?> i : extraInterfaces) {
+            if (classToMock == i) {
+                throw extraInterfacesCannotContainMockedType(classToMock);
+            }
+        }
+    }
+
+    public void validateMockedType(Class<?> classToMock, Object spiedInstance) {
+        if (classToMock == null || spiedInstance == null) {
+            return;
+        }
+        if (!classToMock.equals(spiedInstance.getClass())) {
+            throw mockedTypeIsInconsistentWithSpiedInstanceType(classToMock, spiedInstance);
+        }
+    }
+
+    public void validateDelegatedInstance(Class<?> classToMock, Object delegatedInstance) {
+        if (classToMock == null || delegatedInstance == null) {
+            return;
+        }
+        if (delegatedInstance.getClass().isAssignableFrom(classToMock)) {
+            throw mockedTypeIsInconsistentWithDelegatedInstanceType(classToMock, delegatedInstance);
+        }
+    }
+
+    public void validateConstructorUse(boolean usingConstructor, SerializableMode mode) {
+        if (usingConstructor && mode == SerializableMode.ACROSS_CLASSLOADERS) {
+            throw usingConstructorWithFancySerializable(mode);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/MockNameImpl.java b/src/main/java/org/mockito/internal/util/MockNameImpl.java
index d8654f3..7759979 100644
--- a/src/main/java/org/mockito/internal/util/MockNameImpl.java
+++ b/src/main/java/org/mockito/internal/util/MockNameImpl.java
@@ -2,48 +2,48 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util;

-

-import org.mockito.mock.MockName;

-

-import java.io.Serializable;

-

-public class MockNameImpl implements MockName, Serializable {

-    

-    private static final long serialVersionUID = 8014974700844306925L;

-    private final String mockName;

-    private boolean defaultName;

-

-    @SuppressWarnings("unchecked")

-    public MockNameImpl(String mockName, Class classToMock) {

-        if (mockName == null) {

-            this.mockName = toInstanceName(classToMock);

-            this.defaultName = true;

-        } else {

-            this.mockName = mockName;

-        }

-    }

-

-    public MockNameImpl(String mockName) {

-        this.mockName = mockName;

-    }

-

-    private static String toInstanceName(Class<?> clazz) {

-        String className = clazz.getSimpleName();

-        if (className.length() == 0) {

-            //it's an anonymous class, let's get name from the parent

-            className = clazz.getSuperclass().getSimpleName();

-        }

-        //lower case first letter

-        return className.substring(0, 1).toLowerCase() + className.substring(1);

-    }

-    

-    public boolean isDefault() {

-        return defaultName;

-    }

-    

-    @Override

-    public String toString() {

-        return mockName;

-    }

-}

+package org.mockito.internal.util;
+
+import org.mockito.mock.MockName;
+
+import java.io.Serializable;
+
+public class MockNameImpl implements MockName, Serializable {
+
+    private static final long serialVersionUID = 8014974700844306925L;
+    private final String mockName;
+    private boolean defaultName;
+
+    @SuppressWarnings("unchecked")
+    public MockNameImpl(String mockName, Class<?> classToMock) {
+        if (mockName == null) {
+            this.mockName = toInstanceName(classToMock);
+            this.defaultName = true;
+        } else {
+            this.mockName = mockName;
+        }
+    }
+
+    public MockNameImpl(String mockName) {
+        this.mockName = mockName;
+    }
+
+    private static String toInstanceName(Class<?> clazz) {
+        String className = clazz.getSimpleName();
+        if (className.length() == 0) {
+            //it's an anonymous class, let's get name from the parent
+            className = clazz.getSuperclass().getSimpleName();
+        }
+        //lower case first letter
+        return className.substring(0, 1).toLowerCase() + className.substring(1);
+    }
+
+    public boolean isDefault() {
+        return defaultName;
+    }
+
+    @Override
+    public String toString() {
+        return mockName;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/MockUtil.java b/src/main/java/org/mockito/internal/util/MockUtil.java
index 433be78..31d3b8f 100644
--- a/src/main/java/org/mockito/internal/util/MockUtil.java
+++ b/src/main/java/org/mockito/internal/util/MockUtil.java
@@ -1,92 +1,90 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util;

-

-import org.mockito.Mockito;

-import org.mockito.exceptions.misusing.NotAMockException;

-import org.mockito.internal.InternalMockHandler;

-import org.mockito.internal.configuration.plugins.Plugins;

-import org.mockito.internal.creation.settings.CreationSettings;

-import org.mockito.internal.handler.MockHandlerFactory;

-import org.mockito.internal.util.reflection.LenientCopyTool;

-import org.mockito.invocation.MockHandler;

-import org.mockito.mock.MockCreationSettings;

-import org.mockito.mock.MockName;

-import org.mockito.plugins.MockMaker;

-

-import java.lang.reflect.Modifier;

-

-@SuppressWarnings("unchecked")

-public class MockUtil {

-

-    private static final MockMaker mockMaker = Plugins.getMockMaker();

-

-    public boolean isTypeMockable(Class<?> type) {

-      return !type.isPrimitive() && !Modifier.isFinal(type.getModifiers());

-    }

-

-    public <T> T createMock(MockCreationSettings<T> settings) {

-        MockHandler mockHandler = new MockHandlerFactory().create(settings);

-

-        T mock = mockMaker.createMock(settings, mockHandler);

-

-        Object spiedInstance = settings.getSpiedInstance();

-        if (spiedInstance != null) {

-            new LenientCopyTool().copyToMock(spiedInstance, mock);

-        }

-

-        return mock;

-    }

-

-    public <T> void resetMock(T mock) {

-        InternalMockHandler oldHandler = (InternalMockHandler) getMockHandler(mock);

-        MockCreationSettings settings = oldHandler.getMockSettings();

-        MockHandler newHandler = new MockHandlerFactory().create(settings);

-

-        mockMaker.resetMock(mock, newHandler, settings);

-    }

-

-    public <T> InternalMockHandler<T> getMockHandler(T mock) {

-        if (mock == null) {

-            throw new NotAMockException("Argument should be a mock, but is null!");

-        }

-

-        if (isMockitoMock(mock)) {

-            MockHandler handler = mockMaker.getHandler(mock);

-            return (InternalMockHandler) handler;

-        } else {

-            throw new NotAMockException("Argument should be a mock, but is: " + mock.getClass());

-        }

-    }

-

-    public boolean isMock(Object mock) {

-        // double check to avoid classes that have the same interfaces, could be great to have a custom mockito field in the proxy instead of relying on instance fields

-        return isMockitoMock(mock);

-    }

-

-    public boolean isSpy(Object mock) {

-        return isMockitoMock(mock) && getMockSettings(mock).getDefaultAnswer() == Mockito.CALLS_REAL_METHODS;

-    }

-

-    private <T> boolean isMockitoMock(T mock) {

-        return mockMaker.getHandler(mock) != null;

-    }

-

-    public MockName getMockName(Object mock) {

-        return getMockHandler(mock).getMockSettings().getMockName();

-    }

-

-    public void maybeRedefineMockName(Object mock, String newName) {

-        MockName mockName = getMockName(mock);

-        //TODO SF hacky...

-        if (mockName.isDefault() && getMockHandler(mock).getMockSettings() instanceof CreationSettings) {

-            ((CreationSettings) getMockHandler(mock).getMockSettings()).setMockName(new MockNameImpl(newName));

-        }

-    }

-

-    public MockCreationSettings getMockSettings(Object mock) {

-        return getMockHandler(mock).getMockSettings();

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import static org.mockito.internal.handler.MockHandlerFactory.createMockHandler;
+
+import org.mockito.Mockito;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.util.reflection.LenientCopyTool;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.plugins.MockMaker;
+import org.mockito.plugins.MockMaker.TypeMockability;
+
+@SuppressWarnings("unchecked")
+public class MockUtil {
+
+    private static final MockMaker mockMaker = Plugins.getMockMaker();
+
+    private MockUtil() {}
+
+    public static TypeMockability typeMockabilityOf(Class<?> type) {
+      return mockMaker.isTypeMockable(type);
+    }
+
+    public static <T> T createMock(MockCreationSettings<T> settings) {
+        MockHandler mockHandler =  createMockHandler(settings);
+
+        T mock = mockMaker.createMock(settings, mockHandler);
+
+        Object spiedInstance = settings.getSpiedInstance();
+        if (spiedInstance != null) {
+            new LenientCopyTool().copyToMock(spiedInstance, mock);
+        }
+
+        return mock;
+    }
+
+    public static <T> void resetMock(T mock) {
+        InternalMockHandler oldHandler = (InternalMockHandler) getMockHandler(mock);
+        MockCreationSettings settings = oldHandler.getMockSettings();
+        MockHandler newHandler = createMockHandler(settings);
+
+        mockMaker.resetMock(mock, newHandler, settings);
+    }
+
+    public static <T> InternalMockHandler<T> getMockHandler(T mock) {
+        if (mock == null) {
+            throw new NotAMockException("Argument should be a mock, but is null!");
+        }
+
+        if (isMock(mock)) {
+            MockHandler handler = mockMaker.getHandler(mock);
+            return (InternalMockHandler) handler;
+        } else {
+            throw new NotAMockException("Argument should be a mock, but is: " + mock.getClass());
+        }
+    }
+
+    public static boolean isSpy(Object mock) {
+        return isMock(mock) && getMockSettings(mock).getDefaultAnswer() == Mockito.CALLS_REAL_METHODS;
+    }
+
+    public static boolean isMock(Object mock) {
+        return mock != null && mockMaker.getHandler(mock) != null;
+    }
+
+    public static MockName getMockName(Object mock) {
+        return getMockHandler(mock).getMockSettings().getMockName();
+    }
+
+    public static void maybeRedefineMockName(Object mock, String newName) {
+        MockName mockName = getMockName(mock);
+        //TODO SF hacky...
+        MockCreationSettings mockSettings = getMockHandler(mock).getMockSettings();
+		if (mockName.isDefault() && mockSettings instanceof CreationSettings) {
+            ((CreationSettings) mockSettings).setMockName(new MockNameImpl(newName));
+        }
+    }
+
+    public static MockCreationSettings getMockSettings(Object mock) {
+        return getMockHandler(mock).getMockSettings();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/MockitoLogger.java b/src/main/java/org/mockito/internal/util/MockitoLogger.java
index 31117d8..af66cee 100644
--- a/src/main/java/org/mockito/internal/util/MockitoLogger.java
+++ b/src/main/java/org/mockito/internal/util/MockitoLogger.java
@@ -2,10 +2,10 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util;

-

-public interface MockitoLogger {

-

-    void log(Object what);

-

-}
\ No newline at end of file
+package org.mockito.internal.util;
+
+public interface MockitoLogger {
+
+    void log(Object what);
+
+}
diff --git a/src/main/java/org/mockito/internal/util/ObjectMethodsGuru.java b/src/main/java/org/mockito/internal/util/ObjectMethodsGuru.java
index 4e78249..2fc9bce 100644
--- a/src/main/java/org/mockito/internal/util/ObjectMethodsGuru.java
+++ b/src/main/java/org/mockito/internal/util/ObjectMethodsGuru.java
@@ -1,44 +1,29 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util;

-

-import org.mockito.internal.creation.DelegatingMethod;

-import org.mockito.internal.invocation.MockitoMethod;

-

-import java.io.Serializable;

-import java.lang.reflect.Method;

-

-public class ObjectMethodsGuru implements Serializable {

-

-    private static final long serialVersionUID = -1286718569065470494L;

-

-    public boolean isToString(Method method) {

-        return isToString(new DelegatingMethod(method));

-    }

-

-    public boolean isToString(MockitoMethod method) {

-        return method.getReturnType() == String.class

-                && method.getParameterTypes().length == 0

-                && method.getName().equals("toString");

-    }

-

-    public boolean isEqualsMethod(Method method) {

-        return method.getName().equals("equals")

-                && method.getParameterTypes().length == 1

-                && method.getParameterTypes()[0] == Object.class;

-    }

-

-    public boolean isHashCodeMethod(Method method) {

-        return method.getName().equals("hashCode")

-                && method.getParameterTypes().length == 0;

-    }

-

-    public boolean isCompareToMethod(Method method) {

-        return Comparable.class.isAssignableFrom(method.getDeclaringClass())

-                && method.getName().equals("compareTo")

-                && method.getParameterTypes().length == 1

-                && method.getParameterTypes()[0] == method.getDeclaringClass();

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import java.lang.reflect.Method;
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.invocation.MockitoMethod;
+
+public class ObjectMethodsGuru{
+
+    private ObjectMethodsGuru() {
+    }
+
+    public static boolean isToStringMethod(Method method) {
+        MockitoMethod m = new DelegatingMethod(method);
+        return m.getReturnType() == String.class &&
+               m.getParameterTypes().length == 0 &&
+               m.getName().equals("toString");
+    }
+
+    public static boolean isCompareToMethod(Method method) {
+        return Comparable.class.isAssignableFrom(method.getDeclaringClass())
+                && method.getName().equals("compareTo")
+                && method.getParameterTypes().length == 1
+                && method.getParameterTypes()[0] == method.getDeclaringClass();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/Platform.java b/src/main/java/org/mockito/internal/util/Platform.java
new file mode 100644
index 0000000..897ebed
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/Platform.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.mockito.internal.util.StringUtil.join;
+
+public abstract class Platform {
+
+    private static final Pattern JAVA_8_RELEASE_VERSION_SCHEME = Pattern.compile("1\\.8\\.0_(\\d+)(?:-ea)?(?:-b\\d+)?");
+    private static final Pattern JAVA_8_DEV_VERSION_SCHEME = Pattern.compile("1\\.8\\.0b\\d+_u(\\d+)");
+    public static final String JAVA_VERSION = System.getProperty("java.specification.version");
+    public static final String JVM_VERSION = System.getProperty("java.runtime.version");
+    public static final String JVM_VENDOR = System.getProperty("java.vm.vendor");
+    public static final String JVM_VENDOR_VERSION = System.getProperty("java.vm.version");
+    public static final String JVM_NAME = System.getProperty("java.vm.name");
+    public static final String JVM_INFO = System.getProperty("java.vm.info");
+    public static final String OS_NAME = System.getProperty("os.name");
+    public static final String OS_VERSION = System.getProperty("os.version");
+
+    private Platform() {
+    }
+
+    public static boolean isAndroid() {
+        return System.getProperty("java.vendor", "").toLowerCase(Locale.US).contains("android");
+    }
+
+    public static boolean isAndroidMockMakerRequired() {
+        return Boolean.getBoolean("org.mockito.mock.android");
+    }
+
+    public static String describe() {
+        String description = String.format("Java               : %s\n" +
+                             "JVM vendor name    : %s\n" +
+                             "JVM vendor version : %s\n" +
+                             "JVM name           : %s\n" +
+                             "JVM version        : %s\n" +
+                             "JVM info           : %s\n" +
+                             "OS name            : %s\n" +
+                             "OS version         : %s\n",
+                             JAVA_VERSION,
+                             JVM_VENDOR,
+                             JVM_VENDOR_VERSION,
+                             JVM_NAME,
+                             JVM_VERSION,
+                             JVM_INFO,
+                             OS_NAME,
+                             OS_VERSION);
+        if (isAndroid()) {
+            description = join(
+                    "IMPORTANT INFORMATION FOR ANDROID USERS:",
+                    "",
+                    "The regular Byte Buddy mock makers cannot generate code on an Android VM!",
+                    "To resolve this, please use the 'mockito-android' dependency for your application:",
+                    "http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22mockito-android%22%20g%3A%22org.mockito%22",
+                    "",
+                    description
+            );
+        }
+        return description;
+    }
+
+    public static boolean isJava8BelowUpdate45() {
+        return isJava8BelowUpdate45(JVM_VERSION);
+    }
+
+    static boolean isJava8BelowUpdate45(String jvmVersion) {
+        Matcher matcher = JAVA_8_RELEASE_VERSION_SCHEME.matcher(jvmVersion);
+        if (matcher.matches()) {
+            int update = Integer.parseInt(matcher.group(1));
+            return update < 45;
+        }
+
+        matcher = JAVA_8_DEV_VERSION_SCHEME.matcher(jvmVersion);
+        if (matcher.matches()) {
+            int update = Integer.parseInt(matcher.group(1));
+            return update < 45;
+        }
+
+        matcher = Pattern.compile("1\\.8\\.0-b\\d+").matcher(jvmVersion);
+        return matcher.matches();
+
+    }
+
+    public static String warnForVM(String vmName1, String warnMessage1,
+                                   String vmName2, String warnMessage2) {
+        return warnForVM(JVM_NAME,
+                         vmName1, warnMessage1,
+                         vmName2, warnMessage2);
+    }
+
+    static String warnForVM(String current,
+                            String vmName1, String warnMessage1,
+                            String vmName2, String warnMessage2) {
+        if (vmName1 != null && current.contains(vmName1)) {
+            return warnMessage1;
+        }
+        if (vmName2 != null && current.contains(vmName2)) {
+            return warnMessage2;
+        }
+        return "";
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/Primitives.java b/src/main/java/org/mockito/internal/util/Primitives.java
index 4dcc07e..4d813e3 100644
--- a/src/main/java/org/mockito/internal/util/Primitives.java
+++ b/src/main/java/org/mockito/internal/util/Primitives.java
@@ -1,87 +1,94 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util;

-

-import java.util.HashMap;

-import java.util.Map;

-

-@SuppressWarnings("unchecked")

-public class Primitives {

-

-    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPES = new HashMap<Class<?>, Class<?>>();

-    private static final Map<Class<?>, Object> PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES = new HashMap<Class<?>, Object>();

-

-

-    /**

-     * Returns the primitive type of the given class.

-     * <p/>

-     * The passed class can be any class : <code>boolean.class</code>, <code>Integer.class</code>

-     * in witch case this method will return <code>boolean.class</code>, even <code>SomeObject.class</code>

-     * in which case <code>null</code> will be returned.

-     *

-     * @param clazz The class from which primitive type has to be retrieved

-     * @param <T>   The type

-     * @return The primitive type if relevant, otherwise <code>null</code>

-     */

-    public static <T> Class<T> primitiveTypeOf(Class<T> clazz) {

-        if (clazz.isPrimitive()) {

-            return clazz;

-        }

-        return (Class<T>) PRIMITIVE_TYPES.get(clazz);

-    }

-

-    /**

-     * Indicates if the given class is primitive type or a primitive wrapper.

-     *

-     * @param type The type to check

-     * @return <code>true</code> if primitive or wrapper, <code>false</code> otherwise.

-     */

-    public static boolean isPrimitiveOrWrapper(Class<?> type) {

-        return PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.containsKey(type);

-    }

-

-    /**

-     * Returns the boxed default value for a primitive or a primitive wrapper.

-     *

-     * @param primitiveOrWrapperType The type to lookup the default value

-     * @return The boxed default values as defined in Java Language Specification,

-     *         <code>null</code> if the type is neither a primitive nor a wrapper

-     */

-    public static <T> T defaultValueForPrimitiveOrWrapper(Class<T> primitiveOrWrapperType) {

-        return (T) PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.get(primitiveOrWrapperType);

-    }

-

-

-    static {

-        PRIMITIVE_TYPES.put(Boolean.class, Boolean.TYPE);

-        PRIMITIVE_TYPES.put(Character.class, Character.TYPE);

-        PRIMITIVE_TYPES.put(Byte.class, Byte.TYPE);

-        PRIMITIVE_TYPES.put(Short.class, Short.TYPE);

-        PRIMITIVE_TYPES.put(Integer.class, Integer.TYPE);

-        PRIMITIVE_TYPES.put(Long.class, Long.TYPE);

-        PRIMITIVE_TYPES.put(Float.class, Float.TYPE);

-        PRIMITIVE_TYPES.put(Double.class, Double.TYPE);

-    }

-

-    static {

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Boolean.class, false);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Character.class, '\u0000');

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Byte.class, (byte) 0);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Short.class, (short) 0);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Integer.class, 0);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Long.class, 0L);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Float.class, 0F);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Double.class, 0D);

-

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(boolean.class, false);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(char.class, '\u0000');

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(byte.class, (byte) 0);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(short.class, (short) 0);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(int.class, 0);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(long.class, 0L);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(float.class, 0F);

-        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(double.class, 0D);

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings("unchecked")
+public class Primitives {
+
+    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPES = new HashMap<Class<?>, Class<?>>();
+    private static final Map<Class<?>, Object> PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES = new HashMap<Class<?>, Object>();
+
+
+    /**
+     * Returns the primitive type of the given class.
+     * <p/>
+     * The passed class can be any class : <code>boolean.class</code>, <code>Integer.class</code>
+     * in witch case this method will return <code>boolean.class</code>, even <code>SomeObject.class</code>
+     * in which case <code>null</code> will be returned.
+     *
+     * @param clazz The class from which primitive type has to be retrieved
+     * @param <T>   The type
+     * @return The primitive type if relevant, otherwise <code>null</code>
+     */
+    public static <T> Class<T> primitiveTypeOf(Class<T> clazz) {
+        if (clazz.isPrimitive()) {
+            return clazz;
+        }
+        return (Class<T>) PRIMITIVE_TYPES.get(clazz);
+    }
+
+    /**
+     * Indicates if the given class is primitive type or a primitive wrapper.
+     *
+     * @param type The type to check
+     * @return <code>true</code> if primitive or wrapper, <code>false</code> otherwise.
+     */
+    public static boolean isPrimitiveOrWrapper(Class<?> type) {
+        return PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.containsKey(type);
+    }
+
+    public static boolean isAssignableFromWrapper(Class<?> valueClass, Class<?> referenceType) {
+        if(isPrimitiveOrWrapper(valueClass) && isPrimitiveOrWrapper(referenceType)) {
+            return Primitives.primitiveTypeOf(valueClass).isAssignableFrom(referenceType);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the boxed default value for a primitive or a primitive wrapper.
+     *
+     * @param primitiveOrWrapperType The type to lookup the default value
+     * @return The boxed default values as defined in Java Language Specification,
+     *         <code>null</code> if the type is neither a primitive nor a wrapper
+     */
+    public static <T> T defaultValue(Class<T> primitiveOrWrapperType) {
+        return (T) PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.get(primitiveOrWrapperType);
+    }
+
+
+    static {
+        PRIMITIVE_TYPES.put(Boolean.class, Boolean.TYPE);
+        PRIMITIVE_TYPES.put(Character.class, Character.TYPE);
+        PRIMITIVE_TYPES.put(Byte.class, Byte.TYPE);
+        PRIMITIVE_TYPES.put(Short.class, Short.TYPE);
+        PRIMITIVE_TYPES.put(Integer.class, Integer.TYPE);
+        PRIMITIVE_TYPES.put(Long.class, Long.TYPE);
+        PRIMITIVE_TYPES.put(Float.class, Float.TYPE);
+        PRIMITIVE_TYPES.put(Double.class, Double.TYPE);
+    }
+
+    static {
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Boolean.class, false);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Character.class, '\u0000');
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Byte.class, (byte) 0);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Short.class, (short) 0);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Integer.class, 0);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Long.class, 0L);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Float.class, 0F);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(Double.class, 0D);
+
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(boolean.class, false);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(char.class, '\u0000');
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(byte.class, (byte) 0);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(short.class, (short) 0);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(int.class, 0);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(long.class, 0L);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(float.class, 0F);
+        PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.put(double.class, 0D);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/RemoveFirstLine.java b/src/main/java/org/mockito/internal/util/RemoveFirstLine.java
deleted file mode 100644
index 517f88f..0000000
--- a/src/main/java/org/mockito/internal/util/RemoveFirstLine.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.util;

-

-public class RemoveFirstLine {

-

-    /**

-     * @param text to have the first line removed

-     * @return less first line

-     */

-    public String of(String text) {

-        return text.replaceFirst(".*?\n", "");

-    }

-}

diff --git a/src/main/java/org/mockito/internal/util/SimpleMockitoLogger.java b/src/main/java/org/mockito/internal/util/SimpleMockitoLogger.java
deleted file mode 100644
index 6ee40ea..0000000
--- a/src/main/java/org/mockito/internal/util/SimpleMockitoLogger.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.util;

-

-public class SimpleMockitoLogger extends ConsoleMockitoLogger {

-

-    StringBuilder loggedInfo = new StringBuilder();

-

-    public void log(Object what) {

-//            can be uncommented when debugging this test

-//            super.log(what);

-        loggedInfo.append(what);

-    }

-

-    public String getLoggedInfo() {

-        return loggedInfo.toString();

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/util/StringJoiner.java b/src/main/java/org/mockito/internal/util/StringJoiner.java
deleted file mode 100644
index 2cbab0c..0000000
--- a/src/main/java/org/mockito/internal/util/StringJoiner.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.util;
-
-public class StringJoiner {
-
-    public static String join(Object ... linesToBreak) {
-        StringBuilder out = new StringBuilder("\n");
-        return join(out, linesToBreak);
-    }
-
-    private static String join(StringBuilder out, Object[] linesToBreak) {
-        for (Object line : linesToBreak) {
-            out.append(line.toString()).append("\n");
-        }
-        int lastBreak = out.lastIndexOf("\n");
-        return out.replace(lastBreak, lastBreak+1, "").toString();
-    }
-}
diff --git a/src/main/java/org/mockito/internal/util/StringUtil.java b/src/main/java/org/mockito/internal/util/StringUtil.java
new file mode 100644
index 0000000..e1d09ab
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/StringUtil.java
@@ -0,0 +1,69 @@
+package org.mockito.internal.util;
+
+import static java.util.Arrays.asList;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class StringUtil {
+
+    private static final Pattern CAPS = Pattern.compile("([A-Z\\d][^A-Z\\d]*)");
+
+    private StringUtil() {}
+    /**
+     * @param text
+     *            to have the first line removed
+     * @return less first line
+     */
+    public static String removeFirstLine(String text) {
+        return text.replaceFirst(".*?\n", "");
+    }
+
+    /**
+     * Joins Strings with line break character. It adds line break in front, too.
+     * This makes it something like 'format' no really 'join'.
+     */
+    public static String join(Object ... linesToBreak) {
+        return join("\n", asList(linesToBreak));
+    }
+
+    /**
+     * Joins Strings with EOL character
+     */
+    public static String join(String start, Iterable<?> lines) {
+        StringBuilder out = new StringBuilder(start);
+        for (Object line : lines) {
+            out.append(line.toString()).append("\n");
+        }
+        int lastBreak = out.lastIndexOf("\n");
+        return out.replace(lastBreak, lastBreak+1, "").toString();
+    }
+
+    public static String decamelizeMatcher(String className) {
+        if (className.length() == 0) {
+            return "<custom argument matcher>";
+        }
+
+        String decamelized = decamelizeClassName(className);
+
+        if (decamelized.length() == 0) {
+            return "<" + className + ">";
+        }
+
+        return "<" + decamelized + ">";
+    }
+
+    private static String decamelizeClassName(String className) {
+        Matcher match = CAPS.matcher(className);
+        StringBuilder deCameled = new StringBuilder();
+        while (match.find()) {
+            if (deCameled.length() == 0) {
+                deCameled.append(match.group());
+            } else {
+                deCameled.append(" ");
+                deCameled.append(match.group().toLowerCase());
+            }
+        }
+        return deCameled.toString();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/Supplier.java b/src/main/java/org/mockito/internal/util/Supplier.java
new file mode 100644
index 0000000..8a99b8b
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/Supplier.java
@@ -0,0 +1,16 @@
+package org.mockito.internal.util;
+
+/**
+ * Abstract provider that can supply (provide/create) objects of given type.
+ *
+ * Delete when we move to Java 8 and use built-in type.
+ *
+ * @param <T> type of object to provide/create.
+ */
+public interface Supplier<T> {
+
+    /**
+     * Provides an instance.
+     */
+    T get();
+}
diff --git a/src/main/java/org/mockito/internal/util/Timer.java b/src/main/java/org/mockito/internal/util/Timer.java
index b71e4fd..783f580 100644
--- a/src/main/java/org/mockito/internal/util/Timer.java
+++ b/src/main/java/org/mockito/internal/util/Timer.java
@@ -1,11 +1,18 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.util;
 
+import static org.mockito.internal.exceptions.Reporter.cannotCreateTimerWithNegativeDurationTime;
+
 public class Timer {
 
     private final long durationMillis;
     private long startTime = -1;
 
     public Timer(long durationMillis) {
+        validateInput(durationMillis);
         this.durationMillis = durationMillis;
     }
 
@@ -23,4 +30,14 @@
     public void start() {
         startTime = System.currentTimeMillis();
     }
+
+    private void validateInput(long durationMillis) {
+        if (durationMillis < 0) {
+            throw cannotCreateTimerWithNegativeDurationTime(durationMillis);
+        }
+    }
+
+    public long duration() {
+        return durationMillis;
+    }
 }
diff --git a/src/main/java/org/mockito/internal/util/collections/ArrayUtils.java b/src/main/java/org/mockito/internal/util/collections/ArrayUtils.java
deleted file mode 100644
index 1b3859c..0000000
--- a/src/main/java/org/mockito/internal/util/collections/ArrayUtils.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.util.collections;

-

-@SuppressWarnings("unchecked")

-public class ArrayUtils {

-

-    public <T> boolean isEmpty(T[] array) {

-        return array == null || array.length == 0;

-    }

-

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java b/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java
index 22c9d1b..d8b581c 100644
--- a/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java
+++ b/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java
@@ -56,9 +56,8 @@
     }
 
     @Override public String toString() {
-        MockUtil mockUtil = new MockUtil();
         return "HashCodeAndEqualsMockWrapper{" +
-                "mockInstance=" + (mockUtil.isMock(mockInstance) ? mockUtil.getMockName(mockInstance) : typeInstanceString()) +
+                "mockInstance=" + (MockUtil.isMock(mockInstance) ? MockUtil.getMockName(mockInstance) : typeInstanceString()) +
                 '}';
     }
 
diff --git a/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java b/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java
index 466c11a..d422dba 100644
--- a/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java
+++ b/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java
@@ -95,6 +95,7 @@
         return unwrapTo(new Object[size()]);
     }
 
+    @SuppressWarnings("unchecked")
     private <T> T[] unwrapTo(T[] array) {
         Iterator<Object> iterator = iterator();
         for (int i = 0, objectsLength = array.length; i < objectsLength; i++) {
@@ -105,10 +106,9 @@
         return array;
     }
 
-
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] typedArray) {
-        T[] array = typedArray.length >= size() ? typedArray :
-                (T[]) newInstance(typedArray.getClass().getComponentType(), size());
+        T[] array = typedArray.length >= size() ? typedArray : (T[]) newInstance(typedArray.getClass().getComponentType(), size());
         return unwrapTo(array);
     }
 
diff --git a/src/main/java/org/mockito/internal/util/collections/IdentitySet.java b/src/main/java/org/mockito/internal/util/collections/IdentitySet.java
index 661d609..76c6178 100644
--- a/src/main/java/org/mockito/internal/util/collections/IdentitySet.java
+++ b/src/main/java/org/mockito/internal/util/collections/IdentitySet.java
@@ -2,25 +2,25 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util.collections;

-

-import java.util.LinkedList;

-

-@SuppressWarnings("unchecked")

-public class IdentitySet {

-

-    LinkedList list = new LinkedList();

-    

-    public boolean contains(Object o) {

-        for(Object existing:list) {

-            if (existing == o) {

-                return true;

-            }

-        }

-        return false;

-    }

-

-    public void add(Object o) {

-        list.add(o);        

-    }

-}
\ No newline at end of file
+package org.mockito.internal.util.collections;
+
+import java.util.LinkedList;
+
+@SuppressWarnings("unchecked")
+public class IdentitySet {
+
+    private final LinkedList list = new LinkedList();
+
+    public boolean contains(Object o) {
+        for(Object existing:list) {
+            if (existing == o) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void add(Object o) {
+        list.add(o);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/collections/Iterables.java b/src/main/java/org/mockito/internal/util/collections/Iterables.java
index 9aba368..933ce89 100644
--- a/src/main/java/org/mockito/internal/util/collections/Iterables.java
+++ b/src/main/java/org/mockito/internal/util/collections/Iterables.java
@@ -1,6 +1,11 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.util.collections;
 
 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -19,4 +24,19 @@
         }
         return out;
     }
+
+    /**
+     * Returns first element of provided iterable or fails fast when iterable is empty.
+     *
+     * @param iterable non-empty iterable
+     * @return first element of supplied iterable
+     * @throws IllegalArgumentException when supplied iterable is empty
+     */
+    public static <T> T firstOf(Iterable<T> iterable) {
+        Iterator<T> iterator = iterable.iterator();
+        if (!iterator.hasNext()) {
+            throw new IllegalArgumentException("Cannot provide 1st element from empty iterable: " + iterable);
+        }
+        return iterator.next();
+    }
 }
diff --git a/src/main/java/org/mockito/internal/util/collections/ListUtil.java b/src/main/java/org/mockito/internal/util/collections/ListUtil.java
index b426bb2..0a4d268 100644
--- a/src/main/java/org/mockito/internal/util/collections/ListUtil.java
+++ b/src/main/java/org/mockito/internal/util/collections/ListUtil.java
@@ -8,6 +8,12 @@
 import java.util.Collection;
 import java.util.LinkedList;
 
+/**
+ * Basic list/collection operators.
+ * We know that there are existing libraries that implement those use cases neatly.
+ * However, we want to keep Mockito dependencies minimal.
+ * In Java8 we should be able to get rid of this class.
+ */
 public class ListUtil {
 
     public static <T> LinkedList<T> filter(Collection<T> collection, Filter<T> filter) {
@@ -19,8 +25,20 @@
         }
         return filtered;
     }
-    
+
+    public static <From, To> LinkedList<To> convert(Collection<From> collection, Converter<From, To> converter) {
+        LinkedList<To> converted = new LinkedList<To>();
+        for (From f: collection) {
+            converted.add(converter.convert(f));
+        }
+        return converted;
+    }
+
     public interface Filter<T> {
         boolean isOut(T object);
     }
+
+    public interface Converter<From, To> {
+        To convert(From from);
+    }
 }
diff --git a/src/main/java/org/mockito/internal/util/collections/Sets.java b/src/main/java/org/mockito/internal/util/collections/Sets.java
index 6095549..a5a80f1 100644
--- a/src/main/java/org/mockito/internal/util/collections/Sets.java
+++ b/src/main/java/org/mockito/internal/util/collections/Sets.java
@@ -4,8 +4,6 @@
  */
 package org.mockito.internal.util.collections;
 
-
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
diff --git a/src/main/java/org/mockito/internal/util/concurrent/DetachedThreadLocal.java b/src/main/java/org/mockito/internal/util/concurrent/DetachedThreadLocal.java
new file mode 100644
index 0000000..0794178
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/concurrent/DetachedThreadLocal.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.concurrent;
+
+/**
+ * <p>
+ * A detached local that allows for explicit control of setting and removing values from a thread-local
+ * context.
+ * </p>
+ * Instances of this class are non-blocking and fully thread safe.
+ */
+public class DetachedThreadLocal<T> implements Runnable {
+
+    final WeakConcurrentMap<Thread, T> map;
+
+    public DetachedThreadLocal(Cleaner cleaner) {
+        switch (cleaner) {
+            case THREAD:
+            case MANUAL:
+                map = new WeakConcurrentMap<Thread, T>(cleaner == Cleaner.THREAD) {
+                    @Override
+                    protected T defaultValue(Thread key) {
+                        return DetachedThreadLocal.this.initialValue(key);
+                    }
+                };
+                break;
+            case INLINE:
+                map = new WeakConcurrentMap.WithInlinedExpunction<Thread, T>() {
+                    @Override
+                    protected T defaultValue(Thread key) {
+                        return DetachedThreadLocal.this.initialValue(key);
+                    }
+                };
+                break;
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    public T get() {
+        return map.get(Thread.currentThread());
+    }
+
+    public void set(T value) {
+        map.put(Thread.currentThread(), value);
+    }
+
+    public void clear() {
+        map.remove(Thread.currentThread());
+    }
+
+    /**
+     * Clears all thread local references for all threads.
+     */
+    public void clearAll() {
+        map.clear();
+    }
+
+    /**
+     * @param thread The thread to which this thread's thread local value should be pushed.
+     * @return The value being set.
+     */
+    public T pushTo(Thread thread) {
+        T value = get();
+        if (value != null) {
+            map.put(thread, inheritValue(value));
+        }
+        return value;
+    }
+
+    /**
+     * @param thread The thread from which the thread thread local value should be fetched.
+     * @return The value being set.
+     */
+    public T fetchFrom(Thread thread) {
+        T value = map.get(thread);
+        if (value != null) {
+            set(inheritValue(value));
+        }
+        return value;
+    }
+
+    /**
+     * @param thread The thread for which to set a thread-local value.
+     * @return The value accociated with this thread.
+     */
+    public T get(Thread thread) {
+        return map.get(thread);
+    }
+
+    /**
+     * @param thread The thread for which to set a thread-local value.
+     * @param value  The value to set.
+     */
+    public void define(Thread thread, T value) {
+        map.put(thread, value);
+    }
+
+    /**
+     * @param thread The thread for which an initial value is created.
+     * @return The initial value for any thread local. If no default is set, the default value is {@code null}.
+     */
+    protected T initialValue(Thread thread) {
+        return null;
+    }
+
+    /**
+     * @param value The value that is inherited.
+     * @return The inherited value.
+     */
+    protected T inheritValue(T value) {
+        return value;
+    }
+
+    /**
+     * @return The weak map that backs this detached thread local.
+     */
+    public WeakConcurrentMap<Thread, T> getBackingMap() {
+        return map;
+    }
+
+    @Override
+    public void run() {
+        map.run();
+    }
+
+    /**
+     * Determines the cleaning format. A reference is removed either by an explicitly started cleaner thread
+     * associated with this instance ({@link Cleaner#THREAD}), as a result of interacting with this thread local
+     * from any thread ({@link Cleaner#INLINE} or manually by submitting the detached thread local to a thread
+     * ({@link Cleaner#MANUAL}).
+     */
+    public enum Cleaner {
+        THREAD, INLINE, MANUAL
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/concurrent/LICENSE b/src/main/java/org/mockito/internal/util/concurrent/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/concurrent/LICENSE
@@ -0,0 +1,201 @@
+                                 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/src/main/java/org/mockito/internal/util/concurrent/README.md b/src/main/java/org/mockito/internal/util/concurrent/README.md
new file mode 100644
index 0000000..ea18bb4
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/concurrent/README.md
@@ -0,0 +1,19 @@
+This is a miniature implementation of a concurrent, lock-free (as in lock-less) hash map with weak keys where keys respect reference equality. Such a hash map removes entries containing collected keys by either:
+
+1. Inline removal (entries that contain to collected keys are removed as a result of interaction with the map).
+2. Implicit concurrent removal (entries that contain collected keys are removed by an external thread).
+3. Explicit concurrent removal (explicit interaction with the map's reference queue).
+
+As a wrapper around this `WeakConcurrentMap`, this package also contains a `DetachedThreadLocal` which describes a weak concurrent map where the current thread serves as a key of the map. Also, this package delivers a `WeakConcurrentSet` as a wrapper around a weak concurrent map.
+
+This map does not implement the `java.util.Map` interface to simplify the implementation. Writes to the map might cause blocking if many threads write to the map concurrently (this is implied by the maps backing by a `ConcurrentHashMap` and a `ReferenceQueue`), the performance of the map is however significantly better than using a synchronized wrapper around a concurrent hash map.
+
+The library is hosted on *Maven Central* and *JCenter*:
+
+```xml
+<dependency>
+  <groupId>com.blogspot.mydailyjava</groupId>
+  <artifactId>weak-lock-free</artifactId>
+  <version>0.11</version>
+</dependency>
+```
diff --git a/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentMap.java b/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentMap.java
new file mode 100644
index 0000000..c147693
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentMap.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.concurrent;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * <p>
+ * A thread-safe map with weak keys. Entries are based on a key's system hash code and keys are considered
+ * equal only by reference equality.
+ * </p>
+ * This class does not implement the {@link java.util.Map} interface because this implementation is incompatible
+ * with the map contract. While iterating over a map's entries, any key that has not passed iteration is referenced non-weakly.
+ */
+public class WeakConcurrentMap<K, V> extends ReferenceQueue<K> implements Runnable, Iterable<Map.Entry<K, V>> {
+
+    private static final AtomicLong ID = new AtomicLong();
+
+    final ConcurrentMap<WeakKey<K>, V> target;
+
+    private final Thread thread;
+
+    /**
+     * @param cleanerThread {@code true} if a thread should be started that removes stale entries.
+     */
+    public WeakConcurrentMap(boolean cleanerThread) {
+        target = new ConcurrentHashMap<WeakKey<K>, V>();
+        if (cleanerThread) {
+            thread = new Thread(this);
+            thread.setName("weak-ref-cleaner-" + ID.getAndIncrement());
+            thread.setPriority(Thread.MIN_PRIORITY);
+            thread.setDaemon(true);
+            thread.start();
+        } else {
+            thread = null;
+        }
+    }
+
+    /**
+     * @param key The key of the entry.
+     * @return The value of the entry or the default value if it did not exist.
+     */
+    public V get(K key) {
+        if (key == null) throw new NullPointerException();
+        V value = target.get(new LatentKey<K>(key));
+        if (value == null) {
+            value = defaultValue(key);
+            if (value != null) {
+                V previousValue = target.putIfAbsent(new WeakKey<K>(key, this), value);
+                if (previousValue != null) {
+                    value = previousValue;
+                }
+            }
+        }
+        return value;
+    }
+
+    /**
+     * @param key The key of the entry.
+     * @return {@code true} if the key already defines a value.
+     */
+    public boolean containsKey(K key) {
+        if (key == null) throw new NullPointerException();
+        return target.containsKey(new LatentKey<K>(key));
+    }
+
+    /**
+     * @param key   The key of the entry.
+     * @param value The value of the entry.
+     * @return The previous entry or {@code null} if it does not exist.
+     */
+    public V put(K key, V value) {
+        if (key == null || value == null) throw new NullPointerException();
+        return target.put(new WeakKey<K>(key, this), value);
+    }
+
+    /**
+     * @param key The key of the entry.
+     * @return The removed entry or {@code null} if it does not exist.
+     */
+    public V remove(K key) {
+        if (key == null) throw new NullPointerException();
+        return target.remove(new LatentKey<K>(key));
+    }
+
+    /**
+     * Clears the entire map.
+     */
+    public void clear() {
+        target.clear();
+    }
+
+    /**
+     * Creates a default value. There is no guarantee that the requested value will be set as a once it is created
+     * in case that another thread requests a value for a key concurrently.
+     *
+     * @param key The key for which to create a default value.
+     * @return The default value for a key without value or {@code null} for not defining a default value.
+     */
+    protected V defaultValue(K key) {
+        return null;
+    }
+
+    /**
+     * @return The cleaner thread or {@code null} if no such thread was set.
+     */
+    public Thread getCleanerThread() {
+        return thread;
+    }
+
+    /**
+     * Cleans all unused references.
+     */
+    public void expungeStaleEntries() {
+        Reference<?> reference;
+        while ((reference = poll()) != null) {
+            target.remove(reference);
+        }
+    }
+
+    /**
+     * Returns the approximate size of this map where the returned number is at least as big as the actual number of entries.
+     *
+     * @return The minimum size of this map.
+     */
+    public int approximateSize() {
+        return target.size();
+    }
+
+    @Override
+    public void run() {
+        try {
+            while (true) {
+                target.remove(remove());
+            }
+        } catch (InterruptedException ignored) {
+            clear();
+        }
+    }
+
+    @Override
+    public Iterator<Map.Entry<K, V>> iterator() {
+        return new EntryIterator(target.entrySet().iterator());
+    }
+
+    /*
+     * Why this works:
+     * ---------------
+     *
+     * Note that this map only supports reference equality for keys and uses system hash codes. Also, for the
+     * WeakKey instances to function correctly, we are voluntarily breaking the Java API contract for
+     * hashCode/equals of these instances.
+     *
+     *
+     * System hash codes are immutable and can therefore be computed prematurely and are stored explicitly
+     * within the WeakKey instances. This way, we always know the correct hash code of a key and always
+     * end up in the correct bucket of our target map. This remains true even after the weakly referenced
+     * key is collected.
+     *
+     * If we are looking up the value of the current key via WeakConcurrentMap::get or any other public
+     * API method, we know that any value associated with this key must still be in the map as the mere
+     * existence of this key makes it ineligible for garbage collection. Therefore, looking up a value
+     * using another WeakKey wrapper guarantees a correct result.
+     *
+     * If we are looking up the map entry of a WeakKey after polling it from the reference queue, we know
+     * that the actual key was already collected and calling WeakKey::get returns null for both the polled
+     * instance and the instance within the map. Since we explicitly stored the identity hash code for the
+     * referenced value, it is however trivial to identify the correct bucket. From this bucket, the first
+     * weak key with a null reference is removed. Due to hash collision, we do not know if this entry
+     * represents the weak key. However, we do know that the reference queue polls at least as many weak
+     * keys as there are stale map entries within the target map. If no key is ever removed from the map
+     * explicitly, the reference queue eventually polls exactly as many weak keys as there are stale entries.
+     *
+     * Therefore, we can guarantee that there is no memory leak.
+     */
+
+    private static class WeakKey<T> extends WeakReference<T> {
+
+        private final int hashCode;
+
+        WeakKey(T key, ReferenceQueue<? super T> queue) {
+            super(key, queue);
+            hashCode = System.identityHashCode(key);
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof LatentKey<?>) {
+                return ((LatentKey<?>) other).key == get();
+            } else {
+                return ((WeakKey<?>) other).get() == get();
+            }
+        }
+    }
+
+    /*
+     * A latent key must only be used for looking up instances within a map. For this to work, it implements an identical contract for
+     * hash code and equals as the WeakKey implementation. At the same time, the latent key implementation does not extend WeakReference
+     * and avoids the overhead that a weak reference implies.
+     */
+
+    private static class LatentKey<T> {
+
+        final T key;
+
+        private final int hashCode;
+
+        LatentKey(T key) {
+            this.key = key;
+            hashCode = System.identityHashCode(key);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof LatentKey<?>) {
+                return ((LatentKey<?>) other).key == key;
+            } else {
+                return ((WeakKey<?>) other).get() == key;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+    }
+
+    /**
+     * A {@link WeakConcurrentMap} where stale entries are removed as a side effect of interacting with this map.
+     */
+    public static class WithInlinedExpunction<K, V> extends WeakConcurrentMap<K, V> {
+
+        public WithInlinedExpunction() {
+            super(false);
+        }
+
+        @Override
+        public V get(K key) {
+            expungeStaleEntries();
+            return super.get(key);
+        }
+
+        @Override
+        public boolean containsKey(K key) {
+            expungeStaleEntries();
+            return super.containsKey(key);
+        }
+
+        @Override
+        public V put(K key, V value) {
+            expungeStaleEntries();
+            return super.put(key, value);
+        }
+
+        @Override
+        public V remove(K key) {
+            expungeStaleEntries();
+            return super.remove(key);
+        }
+
+        @Override
+        public Iterator<Map.Entry<K, V>> iterator() {
+            expungeStaleEntries();
+            return super.iterator();
+        }
+
+        @Override
+        public int approximateSize() {
+            expungeStaleEntries();
+            return super.approximateSize();
+        }
+    }
+
+    private class EntryIterator implements Iterator<Map.Entry<K, V>> {
+
+        private final Iterator<Map.Entry<WeakKey<K>, V>> iterator;
+
+        private Map.Entry<WeakKey<K>, V> nextEntry;
+
+        private K nextKey;
+
+        private EntryIterator(Iterator<Map.Entry<WeakKey<K>, V>> iterator) {
+            this.iterator = iterator;
+            findNext();
+        }
+
+        private void findNext() {
+            while (iterator.hasNext()) {
+                nextEntry = iterator.next();
+                nextKey = nextEntry.getKey().get();
+                if (nextKey != null) {
+                    return;
+                }
+            }
+            nextEntry = null;
+            nextKey = null;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return nextKey != null;
+        }
+
+        @Override
+        public Map.Entry<K, V> next() {
+            if (nextKey == null) {
+                throw new NoSuchElementException();
+            }
+            try {
+                return new SimpleEntry(nextKey, nextEntry);
+            } finally {
+                findNext();
+            }
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private class SimpleEntry implements Map.Entry<K, V> {
+
+        private final K key;
+
+        final Map.Entry<WeakKey<K>, V> entry;
+
+        private SimpleEntry(K key, Map.Entry<WeakKey<K>, V> entry) {
+            this.key = key;
+            this.entry = entry;
+        }
+
+        @Override
+        public K getKey() {
+            return key;
+        }
+
+        @Override
+        public V getValue() {
+            return entry.getValue();
+        }
+
+        @Override
+        public V setValue(V value) {
+            if (value == null) throw new NullPointerException();
+            return entry.setValue(value);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentSet.java b/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentSet.java
new file mode 100644
index 0000000..0f1cde6
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentSet.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.concurrent;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * <p>
+ * A thread-safe set with weak values. Entries are based on a key's system hash code and keys are considered equal only by reference equality.
+ * </p>
+ * This class does not implement the {@link java.util.Set} interface because this implementation is incompatible
+ * with the set contract. While iterating over a set's entries, any value that has not passed iteration is referenced non-weakly.
+ */
+public class WeakConcurrentSet<V> implements Runnable, Iterable<V> {
+
+    final WeakConcurrentMap<V, Boolean> target;
+
+    public WeakConcurrentSet(Cleaner cleaner) {
+        switch (cleaner) {
+            case INLINE:
+                target = new WeakConcurrentMap.WithInlinedExpunction<V, Boolean>();
+                break;
+            case THREAD:
+            case MANUAL:
+                target = new WeakConcurrentMap<V, Boolean>(cleaner == Cleaner.THREAD);
+                break;
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    /**
+     * @param value The value to add to the set.
+     * @return {@code true} if the value was added to the set and was not contained before.
+     */
+    public boolean add(V value) {
+        return target.put(value, Boolean.TRUE) == null; // is null or Boolean.TRUE
+    }
+
+    /**
+     * @param value The value to check if it is contained in the set.
+     * @return {@code true} if the set contains the value.
+     */
+    public boolean contains(V value) {
+        return target.containsKey(value);
+    }
+
+    /**
+     * @param value The value to remove from the set.
+     * @return {@code true} if the value is contained in the set.
+     */
+    public boolean remove(V value) {
+        return target.remove(value);
+    }
+
+    /**
+     * Clears the set.
+     */
+    public void clear() {
+        target.clear();
+    }
+
+    /**
+     * Returns the approximate size of this set where the returned number is at least as big as the actual number of entries.
+     *
+     * @return The minimum size of this set.
+     */
+    public int approximateSize() {
+        return target.approximateSize();
+    }
+
+    @Override
+    public void run() {
+        target.run();
+    }
+
+    /**
+     * Determines the cleaning format. A reference is removed either by an explicitly started cleaner thread
+     * associated with this instance ({@link Cleaner#THREAD}), as a result of interacting with this thread local
+     * from any thread ({@link Cleaner#INLINE} or manually by submitting the detached thread local to a thread
+     * ({@link Cleaner#MANUAL}).
+     */
+    public enum Cleaner {
+        THREAD, INLINE, MANUAL
+    }
+
+    /**
+     * Cleans all unused references.
+     */
+    public void expungeStaleEntries() {
+        target.expungeStaleEntries();
+    }
+
+    /**
+     * @return The cleaner thread or {@code null} if no such thread was set.
+     */
+    public Thread getCleanerThread() {
+        return target.getCleanerThread();
+    }
+
+    @Override
+    public Iterator<V> iterator() {
+        return new ReducingIterator<V>(target.iterator());
+    }
+
+    private static class ReducingIterator<V> implements Iterator<V> {
+
+        private final Iterator<Map.Entry<V, Boolean>> iterator;
+
+        private ReducingIterator(Iterator<Map.Entry<V, Boolean>> iterator) {
+            this.iterator = iterator;
+        }
+
+        @Override
+        public void remove() {
+            iterator.remove();
+        }
+
+        @Override
+        public V next() {
+            return iterator.next().getKey();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return iterator.hasNext();
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/io/IOUtil.java b/src/main/java/org/mockito/internal/util/io/IOUtil.java
index 2b90c2c..42bbfd9 100644
--- a/src/main/java/org/mockito/internal/util/io/IOUtil.java
+++ b/src/main/java/org/mockito/internal/util/io/IOUtil.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.internal.util.io;
 
 import org.mockito.exceptions.base.MockitoException;
diff --git a/src/main/java/org/mockito/internal/util/junit/JUnitFailureHacker.java b/src/main/java/org/mockito/internal/util/junit/JUnitFailureHacker.java
deleted file mode 100644
index debc871..0000000
--- a/src/main/java/org/mockito/internal/util/junit/JUnitFailureHacker.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.internal.util.junit;

-

-import org.junit.runner.notification.Failure;

-import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;

-import org.mockito.internal.util.reflection.Whitebox;

-

-public class JUnitFailureHacker {

-

-    public void appendWarnings(Failure failure, String warnings) {

-        if (isEmpty(warnings)) {

-            return;

-        }

-        //TODO: this has to protect the use in case jUnit changes and this internal state logic fails

-        Throwable throwable = (Throwable) Whitebox.getInternalState(failure, "fThrownException");

-

-        String newMessage = "contains both: actual test failure *and* Mockito warnings.\n" +

-                warnings + "\n *** The actual failure is because of: ***\n";

-

-        ExceptionIncludingMockitoWarnings e = new ExceptionIncludingMockitoWarnings(newMessage, throwable);

-        e.setStackTrace(throwable.getStackTrace());

-        Whitebox.setInternalState(failure, "fThrownException", e);

-    }

-

-    private boolean isEmpty(String warnings) {

-        return warnings == null || "".equals(warnings); // isEmpty() is in JDK 6+ 

-    }   

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/util/package-info.java b/src/main/java/org/mockito/internal/util/package-info.java
new file mode 100644
index 0000000..ddf4e3e
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Static utils
+ */
+package org.mockito.internal.util;
diff --git a/src/main/java/org/mockito/internal/util/package.html b/src/main/java/org/mockito/internal/util/package.html
deleted file mode 100644
index b86ca1c..0000000
--- a/src/main/java/org/mockito/internal/util/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Static utils
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/util/reflection/AccessibilityChanger.java b/src/main/java/org/mockito/internal/util/reflection/AccessibilityChanger.java
index a1d59c3..f02acbe 100644
--- a/src/main/java/org/mockito/internal/util/reflection/AccessibilityChanger.java
+++ b/src/main/java/org/mockito/internal/util/reflection/AccessibilityChanger.java
@@ -2,31 +2,31 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.AccessibleObject;

-

-public class AccessibilityChanger {

-    

-    private Boolean wasAccessible = null;

-

-    /**

-     * safely disables access

-     */

-    public void safelyDisableAccess(AccessibleObject accessibleObject) {

-        assert wasAccessible != null : "accessibility info shall not be null";

-        try {

-            accessibleObject.setAccessible(wasAccessible);

-        } catch (Throwable t) {

-            //ignore

-        }

-    }

-

-    /**

-     * changes the accessibleObject accessibility and returns true if accessibility was changed

-     */

-    public void enableAccess(AccessibleObject accessibleObject) {

-        wasAccessible = accessibleObject.isAccessible();

-        accessibleObject.setAccessible(true);

-    }

-}

+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.AccessibleObject;
+
+public class AccessibilityChanger {
+
+    private Boolean wasAccessible = null;
+
+    /**
+     * safely disables access
+     */
+    public void safelyDisableAccess(AccessibleObject accessibleObject) {
+        assert wasAccessible != null : "accessibility info shall not be null";
+        try {
+            accessibleObject.setAccessible(wasAccessible);
+        } catch (Throwable t) {
+            //ignore
+        }
+    }
+
+    /**
+     * changes the accessibleObject accessibility and returns true if accessibility was changed
+     */
+    public void enableAccess(AccessibleObject accessibleObject) {
+        wasAccessible = accessibleObject.isAccessible();
+        accessibleObject.setAccessible(true);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/BeanPropertySetter.java b/src/main/java/org/mockito/internal/util/reflection/BeanPropertySetter.java
index 082231d..9ef9481 100644
--- a/src/main/java/org/mockito/internal/util/reflection/BeanPropertySetter.java
+++ b/src/main/java/org/mockito/internal/util/reflection/BeanPropertySetter.java
@@ -1,98 +1,98 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.Field;

-import java.lang.reflect.InvocationTargetException;

-import java.lang.reflect.Method;

-import java.util.Locale;

-

-/**

- * This utility class will call the setter of the property to inject a new value.

- */

-public class BeanPropertySetter {

-

-    private static final String SET_PREFIX = "set";

-

-    private final Object target;

-    private final boolean reportNoSetterFound;

-    private final Field field;

-

-    /**

-     * New BeanPropertySetter

-     * @param target The target on which the setter must be invoked

-     * @param propertyField The field that should be accessed with the setter

-     * @param reportNoSetterFound Allow the set method to raise an Exception if the setter cannot be found

-     */

-    public BeanPropertySetter(final Object target, final Field propertyField, boolean reportNoSetterFound) {

-        this.field = propertyField;

-        this.target = target;

-        this.reportNoSetterFound = reportNoSetterFound;

-    }

-

-    /**

-     * New BeanPropertySetter that don't report failure

-     * @param target The target on which the setter must be invoked

-     * @param propertyField The propertyField that must be accessed through a setter

-     */

-    public BeanPropertySetter(final Object target, final Field propertyField) {

-        this(target, propertyField, false);

-    }

-

-    /**

-     * Set the value to the property represented by this {@link BeanPropertySetter}

-     * @param value the new value to pass to the property setter

-     * @return <code>true</code> if the value has been injected, <code>false</code> otherwise

-     * @throws RuntimeException Can be thrown if the setter threw an exception, if the setter is not accessible

-     *          or, if <code>reportNoSetterFound</code> and setter could not be found.

-     */

-    public boolean set(final Object value) {

-

-        AccessibilityChanger changer = new AccessibilityChanger();

-        Method writeMethod = null;

-        try {

-            writeMethod = target.getClass().getMethod(setterName(field.getName()), field.getType());

-

-            changer.enableAccess(writeMethod);

-            writeMethod.invoke(target, value);

-            return true;

-        } catch (InvocationTargetException e) {

-            throw new RuntimeException("Setter '" + writeMethod + "' of '" + target + "' with value '" + value + "' threw exception : '" + e.getTargetException() + "'", e);

-        } catch (IllegalAccessException e) {

-            throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);

-        } catch (NoSuchMethodException e) {

-            reportNoSetterFound();

-        } finally {

-            if(writeMethod != null) {

-                changer.safelyDisableAccess(writeMethod);

-            }

-        }

-

-        reportNoSetterFound();

-        return false;

-    }

-

-    /**

-     * Retrieve the setter name from the field name.

-     *

-     * <p>Implementation is based on the code of {@link java.beans.Introspector}.</p>

-     *

-     * @param fieldName the Field name

-     * @return Setter name.

-     */

-    private String setterName(String fieldName) {

-        return new StringBuilder(SET_PREFIX)

-                .append(fieldName.substring(0, 1).toUpperCase(Locale.ENGLISH))

-                .append(fieldName.substring(1))

-                .toString();

-    }

-

-    private void reportNoSetterFound() {

-        if(reportNoSetterFound) {

-            throw new RuntimeException("Problems setting value on object: [" + target + "] for property : [" + field.getName() + "], setter not found");

-        }

-    }

-

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+/**
+ * This utility class will call the setter of the property to inject a new value.
+ */
+public class BeanPropertySetter {
+
+    private static final String SET_PREFIX = "set";
+
+    private final Object target;
+    private final boolean reportNoSetterFound;
+    private final Field field;
+
+    /**
+     * New BeanPropertySetter
+     * @param target The target on which the setter must be invoked
+     * @param propertyField The field that should be accessed with the setter
+     * @param reportNoSetterFound Allow the set method to raise an Exception if the setter cannot be found
+     */
+    public BeanPropertySetter(final Object target, final Field propertyField, boolean reportNoSetterFound) {
+        this.field = propertyField;
+        this.target = target;
+        this.reportNoSetterFound = reportNoSetterFound;
+    }
+
+    /**
+     * New BeanPropertySetter that don't report failure
+     * @param target The target on which the setter must be invoked
+     * @param propertyField The propertyField that must be accessed through a setter
+     */
+    public BeanPropertySetter(final Object target, final Field propertyField) {
+        this(target, propertyField, false);
+    }
+
+    /**
+     * Set the value to the property represented by this {@link BeanPropertySetter}
+     * @param value the new value to pass to the property setter
+     * @return <code>true</code> if the value has been injected, <code>false</code> otherwise
+     * @throws RuntimeException Can be thrown if the setter threw an exception, if the setter is not accessible
+     *          or, if <code>reportNoSetterFound</code> and setter could not be found.
+     */
+    public boolean set(final Object value) {
+
+        AccessibilityChanger changer = new AccessibilityChanger();
+        Method writeMethod = null;
+        try {
+            writeMethod = target.getClass().getMethod(setterName(field.getName()), field.getType());
+
+            changer.enableAccess(writeMethod);
+            writeMethod.invoke(target, value);
+            return true;
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException("Setter '" + writeMethod + "' of '" + target + "' with value '" + value + "' threw exception : '" + e.getTargetException() + "'", e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);
+        } catch (NoSuchMethodException e) {
+            reportNoSetterFound();
+        } finally {
+            if(writeMethod != null) {
+                changer.safelyDisableAccess(writeMethod);
+            }
+        }
+
+        reportNoSetterFound();
+        return false;
+    }
+
+    /**
+     * Retrieve the setter name from the field name.
+     *
+     * <p>Implementation is based on the code of {@link java.beans.Introspector}.</p>
+     *
+     * @param fieldName the Field name
+     * @return Setter name.
+     */
+    private String setterName(String fieldName) {
+        return new StringBuilder(SET_PREFIX)
+                .append(fieldName.substring(0, 1).toUpperCase(Locale.ENGLISH))
+                .append(fieldName.substring(1))
+                .toString();
+    }
+
+    private void reportNoSetterFound() {
+        if(reportNoSetterFound) {
+            throw new RuntimeException("Problems setting value on object: [" + target + "] for property : [" + field.getName() + "], setter not found");
+        }
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/Constructors.java b/src/main/java/org/mockito/internal/util/reflection/Constructors.java
deleted file mode 100644
index 909de8c..0000000
--- a/src/main/java/org/mockito/internal/util/reflection/Constructors.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.mockito.internal.util.reflection;
-
-import java.lang.reflect.Constructor;
-
-public abstract class Constructors {
-
-    /**
-     * Returns the no arg constructor of the type if any.
-     *
-     * @param classToMock The type to look for a no-arg constructor
-     * @return The no-arg constructor or null if none is declared.
-     */
-    public static Constructor<?> noArgConstructorOf(Class<?> classToMock) {
-        try {
-            return classToMock.getDeclaredConstructor();
-        } catch (NoSuchMethodException e) {
-            return null;
-        }
-    }
-}
diff --git a/src/main/java/org/mockito/internal/util/reflection/FieldCopier.java b/src/main/java/org/mockito/internal/util/reflection/FieldCopier.java
index bc6bcff..67f7203 100644
--- a/src/main/java/org/mockito/internal/util/reflection/FieldCopier.java
+++ b/src/main/java/org/mockito/internal/util/reflection/FieldCopier.java
@@ -2,14 +2,14 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.Field;

-

-public class FieldCopier {

-

-    public <T> void copyValue(T from, T to, Field field) throws IllegalAccessException {

-        Object value = field.get(from);

-        field.set(to, value);

-    }

-}

+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+
+public class FieldCopier {
+
+    public <T> void copyValue(T from, T to, Field field) throws IllegalAccessException {
+        Object value = field.get(from);
+        field.set(to, value);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/FieldInitializer.java b/src/main/java/org/mockito/internal/util/reflection/FieldInitializer.java
index ec4b68e..609b30e 100644
--- a/src/main/java/org/mockito/internal/util/reflection/FieldInitializer.java
+++ b/src/main/java/org/mockito/internal/util/reflection/FieldInitializer.java
@@ -1,291 +1,303 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util.reflection;

-

-import org.mockito.exceptions.base.MockitoException;

-import org.mockito.internal.util.MockUtil;

-

-import java.lang.reflect.Constructor;

-import java.lang.reflect.Field;

-import java.lang.reflect.InvocationTargetException;

-import java.lang.reflect.Modifier;

-import java.util.Arrays;

-import java.util.Collections;

-import java.util.Comparator;

-import java.util.List;

-

-/**

- * Initialize a field with type instance if a default constructor can be found.

- *

- * <p>

- * If the given field is already initialized, then <strong>the actual instance is returned</strong>.

- * This initializer doesn't work with inner classes, local classes, interfaces or abstract types.

- * </p>

- *

- */

-public class FieldInitializer {

-

-    private final Object fieldOwner;

-    private final Field field;

-    private final ConstructorInstantiator instantiator;

-

-

-    /**

-     * Prepare initializer with the given field on the given instance.

-     *

-     * <p>

-     * This constructor fail fast if the field type cannot be handled.

-     * </p>

-     *

-     * @param fieldOwner Instance of the test.

-     * @param field Field to be initialize.

-     */

-    public FieldInitializer(Object fieldOwner, Field field) {

-        this(fieldOwner, field, new NoArgConstructorInstantiator(fieldOwner, field));

-    }

-

-    /**

-     * Prepare initializer with the given field on the given instance.

-     *

-     * <p>

-     * This constructor fail fast if the field type cannot be handled.

-     * </p>

-     *

-     * @param fieldOwner Instance of the test.

-     * @param field Field to be initialize.

-     * @param argResolver Constructor parameters resolver

-     */

-    public FieldInitializer(Object fieldOwner, Field field, ConstructorArgumentResolver argResolver) {

-        this(fieldOwner, field, new ParameterizedConstructorInstantiator(fieldOwner, field, argResolver));

-    }

-

-    private FieldInitializer(Object fieldOwner, Field field, ConstructorInstantiator instantiator) {

-        if(new FieldReader(fieldOwner, field).isNull()) {

-            checkNotLocal(field);

-            checkNotInner(field);

-            checkNotInterface(field);

-            checkNotAbstract(field);

-        }

-        this.fieldOwner = fieldOwner;

-        this.field = field;

-        this.instantiator = instantiator;

-    }

-

-    /**

-     * Initialize field if not initialized and return the actual instance.

-     *

-     * @return Actual field instance.

-     */

-    public FieldInitializationReport initialize() {

-        final AccessibilityChanger changer = new AccessibilityChanger();

-        changer.enableAccess(field);

-

-        try {

-            return acquireFieldInstance();

-        } catch(IllegalAccessException e) {

-            throw new MockitoException("Problems initializing field '" + field.getName() + "' of type '" + field.getType().getSimpleName() + "'", e);

-        } finally {

-            changer.safelyDisableAccess(field);

-        }

-    }

-

-    private void checkNotLocal(Field field) {

-        if(field.getType().isLocalClass()) {

-            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is a local class.");

-        }

-    }

-

-    private void checkNotInner(Field field) {

-        if(field.getType().isMemberClass() && !Modifier.isStatic(field.getType().getModifiers())) {

-            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an inner class.");

-        }

-    }

-

-    private void checkNotInterface(Field field) {

-        if(field.getType().isInterface()) {

-            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an interface.");

-        }

-    }

-

-    private void checkNotAbstract(Field field) {

-        if(Modifier.isAbstract(field.getType().getModifiers())) {

-            throw new MockitoException("the type '" + field.getType().getSimpleName() + " is an abstract class.");

-        }

-    }

-

-    private FieldInitializationReport acquireFieldInstance() throws IllegalAccessException {

-        Object fieldInstance = field.get(fieldOwner);

-        if(fieldInstance != null) {

-            return new FieldInitializationReport(fieldInstance, false, false);

-        }

-

-        return instantiator.instantiate();

-    }

-

-    /**

-     * Represents the strategy used to resolve actual instances

-     * to be given to a constructor given the argument types.

-     */

-    public interface ConstructorArgumentResolver {

-

-        /**

-         * Try to resolve instances from types.

-         *

-         * <p>

-         * Checks on the real argument type or on the correct argument number

-         * will happen during the field initialization {@link FieldInitializer#initialize()}.

-         * I.e the only responsibility of this method, is to provide instances <strong>if possible</strong>.

-         * </p>

-         *

-         * @param argTypes Constructor argument types, should not be null.

-         * @return The argument instances to be given to the constructor, should not be null.

-         */

-        Object[] resolveTypeInstances(Class<?>... argTypes);

-    }

-

-    private interface ConstructorInstantiator {

-        FieldInitializationReport instantiate();

-    }

-

-    /**

-     * Constructor instantiating strategy for no-arg constructor.

-     *

-     * <p>

-     * If a no-arg constructor can be found then the instance is created using

-     * this constructor.

-     * Otherwise a technical MockitoException is thrown.

-     * </p>

-     */

-    static class NoArgConstructorInstantiator implements ConstructorInstantiator {

-        private final Object testClass;

-        private final Field field;

-

-        /**

-         * Internal, checks are done by FieldInitializer.

-         * Fields are assumed to be accessible.

-         */

-        NoArgConstructorInstantiator(Object testClass, Field field) {

-            this.testClass = testClass;

-            this.field = field;

-        }

-

-        public FieldInitializationReport instantiate() {

-            final AccessibilityChanger changer = new AccessibilityChanger();

-            Constructor<?> constructor = null;

-            try {

-                constructor = field.getType().getDeclaredConstructor();

-                changer.enableAccess(constructor);

-

-                final Object[] noArg = new Object[0];

-                Object newFieldInstance = constructor.newInstance(noArg);

-                new FieldSetter(testClass, field).set(newFieldInstance);

-

-                return new FieldInitializationReport(field.get(testClass), true, false);

-            } catch (NoSuchMethodException e) {

-                throw new MockitoException("the type '" + field.getType().getSimpleName() + "' has no default constructor", e);

-            } catch (InvocationTargetException e) {

-                throw new MockitoException("the default constructor of type '" + field.getType().getSimpleName() + "' has raised an exception (see the stack trace for cause): " + e.getTargetException().toString(), e);

-            } catch (InstantiationException e) {

-                throw new MockitoException("InstantiationException (see the stack trace for cause): " + e.toString(), e);

-            } catch (IllegalAccessException e) {

-                throw new MockitoException("IllegalAccessException (see the stack trace for cause): " + e.toString(), e);

-            } finally {

-                if(constructor != null) {

-                    changer.safelyDisableAccess(constructor);

-                }

-            }

-        }

-    }

-

-    /**

-     * Constructor instantiating strategy for parameterized constructors.

-     *

-     * <p>

-     * Choose the constructor with the highest number of parameters, then

-     * call the ConstructorArgResolver to get actual argument instances.

-     * If the argResolver fail, then a technical MockitoException is thrown is thrown.

-     * Otherwise the instance is created with the resolved arguments.

-     * </p>

-     */

-    static class ParameterizedConstructorInstantiator implements ConstructorInstantiator {

-        private final Object testClass;

-        private final Field field;

-        private final ConstructorArgumentResolver argResolver;

-	      private final MockUtil mockUtil = new MockUtil();

-        private final Comparator<Constructor<?>> byParameterNumber = new Comparator<Constructor<?>>() {

-            public int compare(Constructor<?> constructorA, Constructor<?> constructorB) {

-	            int argLengths = constructorB.getParameterTypes().length - constructorA.getParameterTypes().length;

-	            if (argLengths == 0) {

-		            int constructorAMockableParamsSize = countMockableParams(constructorA);

-		            int constructorBMockableParamsSize = countMockableParams(constructorB);

-		            return constructorBMockableParamsSize - constructorAMockableParamsSize;

-	            }

-	            return argLengths;

-            }

-	        

-	        private int countMockableParams(Constructor<?> constructor) {

-		        int constructorMockableParamsSize = 0;

-		        for (Class<?> aClass : constructor.getParameterTypes()) {

-			        if(mockUtil.isTypeMockable(aClass)){

-				        constructorMockableParamsSize++;

-			        }

-		        }

-		        return constructorMockableParamsSize;

-	        }

-        };

-

-        /**

-         * Internal, checks are done by FieldInitializer.

-         * Fields are assumed to be accessible.

-         */

-        ParameterizedConstructorInstantiator(Object testClass, Field field, ConstructorArgumentResolver argumentResolver) {

-            this.testClass = testClass;

-            this.field = field;

-            this.argResolver = argumentResolver;

-        }

-

-        public FieldInitializationReport instantiate() {

-            final AccessibilityChanger changer = new AccessibilityChanger();

-            Constructor<?> constructor = null;

-            try {

-                constructor = biggestConstructor(field.getType());

-                changer.enableAccess(constructor);

-

-                final Object[] args = argResolver.resolveTypeInstances(constructor.getParameterTypes());

-                Object newFieldInstance = constructor.newInstance(args);

-                new FieldSetter(testClass, field).set(newFieldInstance);

-

-                return new FieldInitializationReport(field.get(testClass), false, true);

-            } catch (IllegalArgumentException e) {

-                throw new MockitoException("internal error : argResolver provided incorrect types for constructor " + constructor + " of type " + field.getType().getSimpleName(), e);

-            } catch (InvocationTargetException e) {

-                throw new MockitoException("the constructor of type '" + field.getType().getSimpleName() + "' has raised an exception (see the stack trace for cause): " + e.getTargetException().toString(), e);

-            } catch (InstantiationException e) {

-                throw new MockitoException("InstantiationException (see the stack trace for cause): " + e.toString(), e);

-            } catch (IllegalAccessException e) {

-                throw new MockitoException("IllegalAccessException (see the stack trace for cause): " + e.toString(), e);

-            } finally {

-                if(constructor != null) {

-                    changer.safelyDisableAccess(constructor);

-                }

-            }

-        }

-

-        private void checkParameterized(Constructor<?> constructor, Field field) {

-            if(constructor.getParameterTypes().length == 0) {

-                throw new MockitoException("the field " + field.getName() + " of type " + field.getType() + " has no parameterized constructor");

-            }

-        }

-

-        private Constructor<?> biggestConstructor(Class<?> clazz) {

-            final List<Constructor<?>> constructors = Arrays.asList(clazz.getDeclaredConstructors());

-            Collections.sort(constructors, byParameterNumber);

-			

-            Constructor<?> constructor = constructors.get(0);

-            checkParameterized(constructor, field);

-            return constructor;

-        }

-    }

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.MockUtil;
+
+import static java.lang.reflect.Modifier.isStatic;
+import static org.mockito.internal.util.reflection.FieldSetter.setField;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Initialize a field with type instance if a default constructor can be found.
+ *
+ * <p>
+ * If the given field is already initialized, then <strong>the actual instance is returned</strong>.
+ * This initializer doesn't work with inner classes, local classes, interfaces or abstract types.
+ * </p>
+ *
+ */
+public class FieldInitializer {
+
+    private final Object fieldOwner;
+    private final Field field;
+    private final ConstructorInstantiator instantiator;
+
+
+    /**
+     * Prepare initializer with the given field on the given instance.
+     *
+     * <p>
+     * This constructor fail fast if the field type cannot be handled.
+     * </p>
+     *
+     * @param fieldOwner Instance of the test.
+     * @param field Field to be initialize.
+     */
+    public FieldInitializer(Object fieldOwner, Field field) {
+        this(fieldOwner, field, new NoArgConstructorInstantiator(fieldOwner, field));
+    }
+
+    /**
+     * Prepare initializer with the given field on the given instance.
+     *
+     * <p>
+     * This constructor fail fast if the field type cannot be handled.
+     * </p>
+     *
+     * @param fieldOwner Instance of the test.
+     * @param field Field to be initialize.
+     * @param argResolver Constructor parameters resolver
+     */
+    public FieldInitializer(Object fieldOwner, Field field, ConstructorArgumentResolver argResolver) {
+        this(fieldOwner, field, new ParameterizedConstructorInstantiator(fieldOwner, field, argResolver));
+    }
+
+    private FieldInitializer(Object fieldOwner, Field field, ConstructorInstantiator instantiator) {
+        if(new FieldReader(fieldOwner, field).isNull()) {
+            checkNotLocal(field);
+            checkNotInner(field);
+            checkNotInterface(field);
+            checkNotEnum(field);
+            checkNotAbstract(field);
+
+        }
+        this.fieldOwner = fieldOwner;
+        this.field = field;
+        this.instantiator = instantiator;
+    }
+
+    /**
+     * Initialize field if not initialized and return the actual instance.
+     *
+     * @return Actual field instance.
+     */
+    public FieldInitializationReport initialize() {
+        final AccessibilityChanger changer = new AccessibilityChanger();
+        changer.enableAccess(field);
+
+        try {
+            return acquireFieldInstance();
+        } catch(IllegalAccessException e) {
+            throw new MockitoException("Problems initializing field '" + field.getName() + "' of type '" + field.getType().getSimpleName() + "'", e);
+        } finally {
+            changer.safelyDisableAccess(field);
+        }
+    }
+
+    private void checkNotLocal(Field field) {
+        if(field.getType().isLocalClass()) {
+            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is a local class.");
+        }
+    }
+
+    private void checkNotInner(Field field) {
+        Class<?> type = field.getType();
+        if(type.isMemberClass() && !isStatic(type.getModifiers())) {
+            throw new MockitoException("the type '" + type.getSimpleName() + "' is an inner non static class.");
+        }
+    }
+
+    private void checkNotInterface(Field field) {
+        if(field.getType().isInterface()) {
+            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an interface.");
+        }
+    }
+
+    private void checkNotAbstract(Field field) {
+        if(Modifier.isAbstract(field.getType().getModifiers())) {
+            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an abstract class.");
+        }
+    }
+
+    private void checkNotEnum(Field field) {
+        if(field.getType().isEnum()) {
+            throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an enum.");
+        }
+    }
+
+
+    private FieldInitializationReport acquireFieldInstance() throws IllegalAccessException {
+        Object fieldInstance = field.get(fieldOwner);
+        if(fieldInstance != null) {
+            return new FieldInitializationReport(fieldInstance, false, false);
+        }
+
+        return instantiator.instantiate();
+    }
+
+    /**
+     * Represents the strategy used to resolve actual instances
+     * to be given to a constructor given the argument types.
+     */
+    public interface ConstructorArgumentResolver {
+
+        /**
+         * Try to resolve instances from types.
+         *
+         * <p>
+         * Checks on the real argument type or on the correct argument number
+         * will happen during the field initialization {@link FieldInitializer#initialize()}.
+         * I.e the only responsibility of this method, is to provide instances <strong>if possible</strong>.
+         * </p>
+         *
+         * @param argTypes Constructor argument types, should not be null.
+         * @return The argument instances to be given to the constructor, should not be null.
+         */
+        Object[] resolveTypeInstances(Class<?>... argTypes);
+    }
+
+    private interface ConstructorInstantiator {
+        FieldInitializationReport instantiate();
+    }
+
+    /**
+     * Constructor instantiating strategy for no-arg constructor.
+     *
+     * <p>
+     * If a no-arg constructor can be found then the instance is created using
+     * this constructor.
+     * Otherwise a technical MockitoException is thrown.
+     * </p>
+     */
+    static class NoArgConstructorInstantiator implements ConstructorInstantiator {
+        private final Object testClass;
+        private final Field field;
+
+        /**
+         * Internal, checks are done by FieldInitializer.
+         * Fields are assumed to be accessible.
+         */
+        NoArgConstructorInstantiator(Object testClass, Field field) {
+            this.testClass = testClass;
+            this.field = field;
+        }
+
+        public FieldInitializationReport instantiate() {
+            final AccessibilityChanger changer = new AccessibilityChanger();
+            Constructor<?> constructor = null;
+            try {
+                constructor = field.getType().getDeclaredConstructor();
+                changer.enableAccess(constructor);
+
+                final Object[] noArg = new Object[0];
+                Object newFieldInstance = constructor.newInstance(noArg);
+                setField(testClass, field,newFieldInstance);
+
+                return new FieldInitializationReport(field.get(testClass), true, false);
+            } catch (NoSuchMethodException e) {
+                throw new MockitoException("the type '" + field.getType().getSimpleName() + "' has no default constructor", e);
+            } catch (InvocationTargetException e) {
+                throw new MockitoException("the default constructor of type '" + field.getType().getSimpleName() + "' has raised an exception (see the stack trace for cause): " + e.getTargetException().toString(), e);
+            } catch (InstantiationException e) {
+                throw new MockitoException("InstantiationException (see the stack trace for cause): " + e.toString(), e);
+            } catch (IllegalAccessException e) {
+                throw new MockitoException("IllegalAccessException (see the stack trace for cause): " + e.toString(), e);
+            } finally {
+                if(constructor != null) {
+                    changer.safelyDisableAccess(constructor);
+                }
+            }
+        }
+    }
+
+    /**
+     * Constructor instantiating strategy for parameterized constructors.
+     *
+     * <p>
+     * Choose the constructor with the highest number of parameters, then
+     * call the ConstructorArgResolver to get actual argument instances.
+     * If the argResolver fail, then a technical MockitoException is thrown is thrown.
+     * Otherwise the instance is created with the resolved arguments.
+     * </p>
+     */
+    static class ParameterizedConstructorInstantiator implements ConstructorInstantiator {
+        private final Object testClass;
+        private final Field field;
+        private final ConstructorArgumentResolver argResolver;
+        private final Comparator<Constructor<?>> byParameterNumber = new Comparator<Constructor<?>>() {
+            public int compare(Constructor<?> constructorA, Constructor<?> constructorB) {
+                int argLengths = constructorB.getParameterTypes().length - constructorA.getParameterTypes().length;
+                if (argLengths == 0) {
+                    int constructorAMockableParamsSize = countMockableParams(constructorA);
+                    int constructorBMockableParamsSize = countMockableParams(constructorB);
+                    return constructorBMockableParamsSize - constructorAMockableParamsSize;
+                }
+                return argLengths;
+            }
+
+            private int countMockableParams(Constructor<?> constructor) {
+                int constructorMockableParamsSize = 0;
+                for (Class<?> aClass : constructor.getParameterTypes()) {
+                    if(MockUtil.typeMockabilityOf(aClass).mockable()){
+                        constructorMockableParamsSize++;
+                    }
+                }
+                return constructorMockableParamsSize;
+            }
+        };
+
+        /**
+         * Internal, checks are done by FieldInitializer.
+         * Fields are assumed to be accessible.
+         */
+        ParameterizedConstructorInstantiator(Object testClass, Field field, ConstructorArgumentResolver argumentResolver) {
+            this.testClass = testClass;
+            this.field = field;
+            this.argResolver = argumentResolver;
+        }
+
+        public FieldInitializationReport instantiate() {
+            final AccessibilityChanger changer = new AccessibilityChanger();
+            Constructor<?> constructor = null;
+            try {
+                constructor = biggestConstructor(field.getType());
+                changer.enableAccess(constructor);
+
+                final Object[] args = argResolver.resolveTypeInstances(constructor.getParameterTypes());
+                Object newFieldInstance = constructor.newInstance(args);
+                setField(testClass, field,newFieldInstance);
+
+                return new FieldInitializationReport(field.get(testClass), false, true);
+            } catch (IllegalArgumentException e) {
+                throw new MockitoException("internal error : argResolver provided incorrect types for constructor " + constructor + " of type " + field.getType().getSimpleName(), e);
+            } catch (InvocationTargetException e) {
+                throw new MockitoException("the constructor of type '" + field.getType().getSimpleName() + "' has raised an exception (see the stack trace for cause): " + e.getTargetException().toString(), e);
+            } catch (InstantiationException e) {
+                throw new MockitoException("InstantiationException (see the stack trace for cause): " + e.toString(), e);
+            } catch (IllegalAccessException e) {
+                throw new MockitoException("IllegalAccessException (see the stack trace for cause): " + e.toString(), e);
+            } finally {
+                if(constructor != null) {
+                    changer.safelyDisableAccess(constructor);
+                }
+            }
+        }
+
+        private void checkParameterized(Constructor<?> constructor, Field field) {
+            if(constructor.getParameterTypes().length == 0) {
+                throw new MockitoException("the field " + field.getName() + " of type " + field.getType() + " has no parameterized constructor");
+            }
+        }
+
+        private Constructor<?> biggestConstructor(Class<?> clazz) {
+            final List<? extends Constructor<?>> constructors = Arrays.asList(clazz.getDeclaredConstructors());
+            Collections.sort(constructors, byParameterNumber);
+
+            Constructor<?> constructor = constructors.get(0);
+            checkParameterized(constructor, field);
+            return constructor;
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/FieldReader.java b/src/main/java/org/mockito/internal/util/reflection/FieldReader.java
index 49a62e7..1cae117 100644
--- a/src/main/java/org/mockito/internal/util/reflection/FieldReader.java
+++ b/src/main/java/org/mockito/internal/util/reflection/FieldReader.java
@@ -2,33 +2,33 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util.reflection;

-

-import org.mockito.exceptions.base.MockitoException;

-

-import java.lang.reflect.Field;

-

-public class FieldReader {

-

-    final Object target;

-    final Field field;

-    final AccessibilityChanger changer = new AccessibilityChanger();

-

-    public FieldReader(Object target, Field field) {

-        this.target = target;

-        this.field = field;

-        changer.enableAccess(field);

-    }

-

-    public boolean isNull() {

-            return read() == null;

-    }

-

-    public Object read() {

-        try {

-            return field.get(target);

-        } catch (Exception e) {

-            throw new MockitoException("Cannot read state from field: " + field + ", on instance: " + target);

-        }

-    }

-}

+package org.mockito.internal.util.reflection;
+
+import org.mockito.exceptions.base.MockitoException;
+
+import java.lang.reflect.Field;
+
+public class FieldReader {
+
+    final Object target;
+    final Field field;
+    final AccessibilityChanger changer = new AccessibilityChanger();
+
+    public FieldReader(Object target, Field field) {
+        this.target = target;
+        this.field = field;
+        changer.enableAccess(field);
+    }
+
+    public boolean isNull() {
+            return read() == null;
+    }
+
+    public Object read() {
+        try {
+            return field.get(target);
+        } catch (Exception e) {
+            throw new MockitoException("Cannot read state from field: " + field + ", on instance: " + target);
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/FieldSetter.java b/src/main/java/org/mockito/internal/util/reflection/FieldSetter.java
index 5972767..69b5b16 100644
--- a/src/main/java/org/mockito/internal/util/reflection/FieldSetter.java
+++ b/src/main/java/org/mockito/internal/util/reflection/FieldSetter.java
@@ -2,31 +2,25 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.Field;

-

-public class FieldSetter {

-

-    private final Object target;

-    private final Field field;

-

-    public FieldSetter(Object target, Field field) {

-        this.target = target;

-        this.field = field;

-    }

-

-    public void set(Object value) {

-        AccessibilityChanger changer = new AccessibilityChanger();

-        changer.enableAccess(field);

-        try {

-            field.set(target, value);

-        } catch (IllegalAccessException e) {

-            throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);

-        } catch (IllegalArgumentException e) {

-            throw new RuntimeException("Wrong argument on field '" + field + "' of object '" + target + "' with value: '" + value + "', \n" +

-                    "reason : " + e.getMessage(), e);

-        }

-        changer.safelyDisableAccess(field);

-    }

-}

+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+
+public class FieldSetter {
+
+    private FieldSetter(){}
+
+    public static void setField(Object target, Field field,Object value) {
+        AccessibilityChanger changer = new AccessibilityChanger();
+        changer.enableAccess(field);
+        try {
+            field.set(target, value);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException("Wrong argument on field '" + field + "' of object '" + target + "' with value: '" + value + "', \n" +
+                    "reason : " + e.getMessage(), e);
+        }
+        changer.safelyDisableAccess(field);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/Fields.java b/src/main/java/org/mockito/internal/util/reflection/Fields.java
index 327dac0..1d1befe 100644
--- a/src/main/java/org/mockito/internal/util/reflection/Fields.java
+++ b/src/main/java/org/mockito/internal/util/reflection/Fields.java
@@ -61,6 +61,7 @@
      * @param annotations Annotation types to check.
      * @return The filter.
      */
+    @SuppressWarnings({"unchecked", "vararg"})
     public static Filter<InstanceField> annotatedBy(final Class<? extends Annotation>... annotations) {
         return new Filter<InstanceField>() {
             public boolean isOut(InstanceField instanceField) {
@@ -89,6 +90,19 @@
         };
     }
 
+    /**
+     * Accept fields with non null value.
+     *
+     * @return The filter.
+     */
+    public static Filter<InstanceField> syntheticField() {
+        return new Filter<InstanceField>() {
+            public boolean isOut(InstanceField instanceField) {
+                return instanceField.isSynthetic();
+            }
+        };
+    }
+
     public static class InstanceFields {
         private final Object instance;
 
diff --git a/src/main/java/org/mockito/internal/util/reflection/GenericMaster.java b/src/main/java/org/mockito/internal/util/reflection/GenericMaster.java
index 2b07930..a477ba4 100644
--- a/src/main/java/org/mockito/internal/util/reflection/GenericMaster.java
+++ b/src/main/java/org/mockito/internal/util/reflection/GenericMaster.java
@@ -1,34 +1,33 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.Field;

-import java.lang.reflect.ParameterizedType;

-import java.lang.reflect.Type;

-

-@SuppressWarnings("unchecked")

-public class GenericMaster {

-

-    /**

-     * Finds the generic type (parametrized type) of the field. If the field is not generic it returns Object.class. 

-     * 

-     * @param field

-     */

-    public Class getGenericType(Field field) {        

-        Type generic = field.getGenericType();

-        if (generic instanceof ParameterizedType) {

-            Type actual = ((ParameterizedType) generic).getActualTypeArguments()[0];

-            if (actual instanceof Class) {

-                return (Class) actual;

-            } else if (actual instanceof ParameterizedType) {

-                //in case of nested generics we don't go deep

-                return (Class) ((ParameterizedType) actual).getRawType();

-            }

-        }

-        

-        return Object.class;

-    }

-

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+public class GenericMaster {
+
+    /**
+     * Finds the generic type (parametrized type) of the field. If the field is not generic it returns Object.class.
+     *
+     * @param field the field to inspect
+     */
+    public Class<?> getGenericType(Field field) {
+        Type generic = field.getGenericType();
+        if (generic instanceof ParameterizedType) {
+            Type actual = ((ParameterizedType) generic).getActualTypeArguments()[0];
+            if (actual instanceof Class) {
+                return (Class<?>) actual;
+            } else if (actual instanceof ParameterizedType) {
+                //in case of nested generics we don't go deep
+                return (Class<?>) ((ParameterizedType) actual).getRawType();
+            }
+        }
+
+        return Object.class;
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/GenericMetadataSupport.java b/src/main/java/org/mockito/internal/util/reflection/GenericMetadataSupport.java
index 80bd908..8efd384 100644
--- a/src/main/java/org/mockito/internal/util/reflection/GenericMetadataSupport.java
+++ b/src/main/java/org/mockito/internal/util/reflection/GenericMetadataSupport.java
@@ -1,627 +1,656 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util.reflection;

-

-

-import org.mockito.exceptions.base.MockitoException;

-import org.mockito.internal.util.Checks;

-

-import java.lang.reflect.*;

-import java.util.*;

-

-

-/**

- * This class can retrieve generic meta-data that the compiler stores on classes

- * and accessible members.

- *

- * <p>

- *     The main idea of this code is to create a Map that will help to resolve return types.

- *     In order to actually work with nested generics, this map will have to be passed along new instances

- *     as a type context.

- * </p>

- *

- * <p>

- *     Hence :

- *     <ul>

- *         <li>A new instance representing the metadata is created using the {@link #inferFrom(Type)} method from a real

- *         <code>Class</code> or from a <code>ParameterizedType</code>, other types are not yet supported.</li>

- *

- *         <li>Then from this metadata, we can extract meta-data for a generic return type of a method, using

- *         {@link #resolveGenericReturnType(Method)}.</li>

- *     </ul>

- * </p>

- *

- * <p>

- * For now this code support the following kind of generic declarations :

- * <pre class="code"><code class="java">

- * interface GenericsNest&lt;K extends Comparable&lt;K&gt; & Cloneable&gt; extends Map&lt;K, Set&lt;Number&gt;&gt; {

- *     Set&lt;Number&gt; remove(Object key); // override with fixed ParameterizedType

- *     List&lt;? super Integer&gt; returning_wildcard_with_class_lower_bound();

- *     List&lt;? super K&gt; returning_wildcard_with_typeVar_lower_bound();

- *     List&lt;? extends K&gt; returning_wildcard_with_typeVar_upper_bound();

- *     K returningK();

- *     &lt;O extends K&gt; List&lt;O&gt; paramType_with_type_params();

- *     &lt;S, T extends S&gt; T two_type_params();

- *     &lt;O extends K&gt; O typeVar_with_type_params();

- *     Number returningNonGeneric();

- * }

- * </code></pre>

- *

- * @see #inferFrom(Type)

- * @see #resolveGenericReturnType(Method)

- * @see org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs

- */

-public abstract class GenericMetadataSupport {

-

-    // public static MockitoLogger logger = new ConsoleMockitoLogger();

-

-    /**

-     * Represents actual type variables resolved for current class.

-     */

-    protected Map<TypeVariable, Type> contextualActualTypeParameters = new HashMap<TypeVariable, Type>();

-

-

-    protected void registerTypeVariablesOn(Type classType) {

-        if (!(classType instanceof ParameterizedType)) {

-            return;

-        }

-        ParameterizedType parameterizedType = (ParameterizedType) classType;

-        TypeVariable[] typeParameters = ((Class<?>) parameterizedType.getRawType()).getTypeParameters();

-        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

-        for (int i = 0; i < actualTypeArguments.length; i++) {

-            TypeVariable typeParameter = typeParameters[i];

-            Type actualTypeArgument = actualTypeArguments[i];

-

-            if (actualTypeArgument instanceof WildcardType) {

-                contextualActualTypeParameters.put(typeParameter, boundsOf((WildcardType) actualTypeArgument));

-            } else if (typeParameter != actualTypeArgument) {

-                contextualActualTypeParameters.put(typeParameter, actualTypeArgument);

-            }

-            // logger.log("For '" + parameterizedType + "' found type variable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualTypeArgument + "(" + System.identityHashCode(typeParameter) + ")" + "' }");

-        }

-    }

-

-    protected void registerTypeParametersOn(TypeVariable[] typeParameters) {

-        for (TypeVariable type : typeParameters) {

-            registerTypeVariableIfNotPresent(type);

-        }

-    }

-

-    private void registerTypeVariableIfNotPresent(TypeVariable typeVariable) {

-        if (!contextualActualTypeParameters.containsKey(typeVariable)) {

-            contextualActualTypeParameters.put(typeVariable, boundsOf(typeVariable));

-            // logger.log("For '" + typeVariable.getGenericDeclaration() + "' found type variable : { '" + typeVariable + "(" + System.identityHashCode(typeVariable) + ")" + "' : '" + boundsOf(typeVariable) + "' }");

-        }

-    }

-

-    /**

-     * @param typeParameter The TypeVariable parameter

-     * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable

-     *         then retrieve BoundedType of this TypeVariable

-     */

-    private BoundedType boundsOf(TypeVariable typeParameter) {

-        if (typeParameter.getBounds()[0] instanceof TypeVariable) {

-            return boundsOf((TypeVariable) typeParameter.getBounds()[0]);

-        }

-        return new TypeVarBoundedType(typeParameter);

-    }

-

-    /**

-     * @param wildCard The WildCard type

-     * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable

-     *         then retrieve BoundedType of this TypeVariable

-     */

-    private BoundedType boundsOf(WildcardType wildCard) {

-        /*

-         *  According to JLS(http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1):

-         *  - Lower and upper can't coexist: (for instance, this is not allowed: <? extends List<String> & super MyInterface>)

-         *  - Multiple bounds are not supported (for instance, this is not allowed: <? extends List<String> & MyInterface>)

-         */

-

-        WildCardBoundedType wildCardBoundedType = new WildCardBoundedType(wildCard);

-        if (wildCardBoundedType.firstBound() instanceof TypeVariable) {

-            return boundsOf((TypeVariable) wildCardBoundedType.firstBound());

-        }

-

-        return wildCardBoundedType;

-    }

-

-

-

-    /**

-     * @return Raw type of the current instance.

-     */

-    public abstract Class<?> rawType();

-

-

-

-    /**

-     * @return Returns extra interfaces <strong>if relevant</strong>, otherwise empty List.

-     */

-    public List<Type> extraInterfaces() {

-        return Collections.emptyList();

-    }

-

-    /**

-     * @return Returns an array with the raw types of {@link #extraInterfaces()} <strong>if relevant</strong>.

-     */

-    public Class<?>[] rawExtraInterfaces() {

-        return new Class[0];

-    }

-

-    /**

-     * @return Returns true if metadata knows about extra-interfaces {@link #extraInterfaces()} <strong>if relevant</strong>.

-     */

-    public boolean hasRawExtraInterfaces() {

-        return rawExtraInterfaces().length > 0;

-    }

-

-

-

-    /**

-     * @return Actual type arguments matching the type variables of the raw type represented by this {@link GenericMetadataSupport} instance.

-     */

-    public Map<TypeVariable, Type> actualTypeArguments() {

-        TypeVariable[] typeParameters = rawType().getTypeParameters();

-        LinkedHashMap<TypeVariable, Type> actualTypeArguments = new LinkedHashMap<TypeVariable, Type>();

-

-        for (TypeVariable typeParameter : typeParameters) {

-

-            Type actualType = getActualTypeArgumentFor(typeParameter);

-

-            actualTypeArguments.put(typeParameter, actualType);

-            // logger.log("For '" + rawType().getCanonicalName() + "' returning explicit TypeVariable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualType +"' }");

-        }

-

-        return actualTypeArguments;

-    }

-

-    protected Type getActualTypeArgumentFor(TypeVariable typeParameter) {

-        Type type = this.contextualActualTypeParameters.get(typeParameter);

-        if (type instanceof TypeVariable) {

-            TypeVariable typeVariable = (TypeVariable) type;

-            return getActualTypeArgumentFor(typeVariable);

-        }

-

-        return type;

-    }

-

-

-

-    /**

-     * Resolve current method generic return type to a {@link GenericMetadataSupport}.

-     *

-     * @param method Method to resolve the return type.

-     * @return {@link GenericMetadataSupport} representing this generic return type.

-     */

-    public GenericMetadataSupport resolveGenericReturnType(Method method) {

-        Type genericReturnType = method.getGenericReturnType();

-        // logger.log("Method '" + method.toGenericString() + "' has return type : " + genericReturnType.getClass().getInterfaces()[0].getSimpleName() + " : " + genericReturnType);

-

-        if (genericReturnType instanceof Class) {

-            return new NotGenericReturnTypeSupport(genericReturnType);

-        }

-        if (genericReturnType instanceof ParameterizedType) {

-            return new ParameterizedReturnType(this, method.getTypeParameters(), (ParameterizedType) method.getGenericReturnType());

-        }

-        if (genericReturnType instanceof TypeVariable) {

-            return new TypeVariableReturnType(this, method.getTypeParameters(), (TypeVariable) genericReturnType);

-        }

-

-        throw new MockitoException("Ouch, it shouldn't happen, type '" + genericReturnType.getClass().getCanonicalName() + "' on method : '" + method.toGenericString() + "' is not supported : " + genericReturnType);

-    }

-

-    /**

-     * Create an new instance of {@link GenericMetadataSupport} inferred from a {@link Type}.

-     *

-     * <p>

-     *     At the moment <code>type</code> can only be a {@link Class} or a {@link ParameterizedType}, otherwise

-     *     it'll throw a {@link MockitoException}.

-     * </p>

-     *

-     * @param type The class from which the {@link GenericMetadataSupport} should be built.

-     * @return The new {@link GenericMetadataSupport}.

-     * @throws MockitoException Raised if type is not a {@link Class} or a {@link ParameterizedType}.

-     */

-    public static GenericMetadataSupport inferFrom(Type type) {

-        Checks.checkNotNull(type, "type");

-        if (type instanceof Class) {

-            return new FromClassGenericMetadataSupport((Class<?>) type);

-        }

-        if (type instanceof ParameterizedType) {

-            return new FromParameterizedTypeGenericMetadataSupport((ParameterizedType) type);

-        }

-

-        throw new MockitoException("Type meta-data for this Type (" + type.getClass().getCanonicalName() + ") is not supported : " + type);

-    }

-

-

-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

-    //// Below are specializations of GenericMetadataSupport that could handle retrieval of possible Types

-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

-

-    /**

-     * Generic metadata implementation for {@link Class}.

-     *

-     * Offer support to retrieve generic metadata on a {@link Class} by reading type parameters and type variables on

-     * the class and its ancestors and interfaces.

-     */

-    private static class FromClassGenericMetadataSupport extends GenericMetadataSupport {

-        private final Class<?> clazz;

-

-        public FromClassGenericMetadataSupport(Class<?> clazz) {

-            this.clazz = clazz;

-

-            for (Class currentExploredClass = clazz;

-                 currentExploredClass != null && currentExploredClass != Object.class;

-                 currentExploredClass = superClassOf(currentExploredClass)

-                ) {

-                readActualTypeParametersOnDeclaringClass(currentExploredClass);

-            }

-        }

-

-        private Class superClassOf(Class currentExploredClass) {

-            Type genericSuperclass = currentExploredClass.getGenericSuperclass();

-            if (genericSuperclass instanceof ParameterizedType) {

-                Type rawType = ((ParameterizedType) genericSuperclass).getRawType();

-                return (Class) rawType;

-            }

-            return (Class) genericSuperclass;

-        }

-

-        private void readActualTypeParametersOnDeclaringClass(Class<?> clazz) {

-            registerTypeParametersOn(clazz.getTypeParameters());

-            registerTypeVariablesOn(clazz.getGenericSuperclass());

-            for (Type genericInterface : clazz.getGenericInterfaces()) {

-                registerTypeVariablesOn(genericInterface);

-            }

-        }

-

-        @Override

-        public Class<?> rawType() {

-            return clazz;

-        }

-    }

-

-

-    /**

-     * Generic metadata implementation for "standalone" {@link ParameterizedType}.

-     *

-     * Offer support to retrieve generic metadata on a {@link ParameterizedType} by reading type variables of

-     * the related raw type and declared type variable of this parameterized type.

-     *

-     * This class is not designed to work on ParameterizedType returned by {@link Method#getGenericReturnType()}, as

-     * the ParameterizedType instance return in these cases could have Type Variables that refer to type declaration(s).

-     * That's what meant the "standalone" word at the beginning of the Javadoc.

-     * Instead use {@link ParameterizedReturnType}.

-     */

-    private static class FromParameterizedTypeGenericMetadataSupport extends GenericMetadataSupport {

-        private final ParameterizedType parameterizedType;

-

-        public FromParameterizedTypeGenericMetadataSupport(ParameterizedType parameterizedType) {

-            this.parameterizedType = parameterizedType;

-            readActualTypeParameters();

-        }

-

-        private void readActualTypeParameters() {

-            registerTypeVariablesOn(parameterizedType.getRawType());

-            registerTypeVariablesOn(parameterizedType);

-        }

-

-        @Override

-        public Class<?> rawType() {

-            return (Class<?>) parameterizedType.getRawType();

-        }

-    }

-

-

-    /**

-     * Generic metadata specific to {@link ParameterizedType} returned via {@link Method#getGenericReturnType()}.

-     */

-    private static class ParameterizedReturnType extends GenericMetadataSupport {

-        private final ParameterizedType parameterizedType;

-        private final TypeVariable[] typeParameters;

-

-        public ParameterizedReturnType(GenericMetadataSupport source, TypeVariable[] typeParameters, ParameterizedType parameterizedType) {

-            this.parameterizedType = parameterizedType;

-            this.typeParameters = typeParameters;

-            this.contextualActualTypeParameters = source.contextualActualTypeParameters;

-

-            readTypeParameters();

-            readTypeVariables();

-        }

-

-        private void readTypeParameters() {

-            registerTypeParametersOn(typeParameters);

-        }

-

-        private void readTypeVariables() {

-            registerTypeVariablesOn(parameterizedType);

-        }

-

-        @Override

-        public Class<?> rawType() {

-            return (Class<?>) parameterizedType.getRawType();

-        }

-

-    }

-

-

-    /**

-     * Generic metadata for {@link TypeVariable} returned via {@link Method#getGenericReturnType()}.

-     */

-    private static class TypeVariableReturnType extends GenericMetadataSupport {

-        private final TypeVariable typeVariable;

-        private final TypeVariable[] typeParameters;

-        private Class<?> rawType;

-

-

-

-        public TypeVariableReturnType(GenericMetadataSupport source, TypeVariable[] typeParameters, TypeVariable typeVariable) {

-            this.typeParameters = typeParameters;

-            this.typeVariable = typeVariable;

-            this.contextualActualTypeParameters = source.contextualActualTypeParameters;

-

-            readTypeParameters();

-            readTypeVariables();

-        }

-

-        private void readTypeParameters() {

-            registerTypeParametersOn(typeParameters);

-        }

-

-        private void readTypeVariables() {

-            for (Type type : typeVariable.getBounds()) {

-                registerTypeVariablesOn(type);

-            }

-            registerTypeParametersOn(new TypeVariable[] { typeVariable });

-            registerTypeVariablesOn(getActualTypeArgumentFor(typeVariable));

-        }

-

-        @Override

-        public Class<?> rawType() {

-            if (rawType == null) {

-                rawType = extractRawTypeOf(typeVariable);

-            }

-            return rawType;

-        }

-

-        private Class<?> extractRawTypeOf(Type type) {

-            if (type instanceof Class) {

-                return (Class<?>) type;

-            }

-            if (type instanceof ParameterizedType) {

-                return (Class<?>) ((ParameterizedType) type).getRawType();

-            }

-            if (type instanceof BoundedType) {

-                return extractRawTypeOf(((BoundedType) type).firstBound());

-            }

-            if (type instanceof TypeVariable) {

-                /*

-                 * If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared

-                 * on the class definition, such as such as List<E>.

-                 */

-                return extractRawTypeOf(contextualActualTypeParameters.get(type));

-            }

-            throw new MockitoException("Raw extraction not supported for : '" + type + "'");

-        }

-

-        @Override

-        public List<Type> extraInterfaces() {

-            Type type = extractActualBoundedTypeOf(typeVariable);

-            if (type instanceof BoundedType) {

-                return Arrays.asList(((BoundedType) type).interfaceBounds());

-            }

-            if (type instanceof ParameterizedType) {

-                return Collections.singletonList(type);

-            }

-            if (type instanceof Class) {

-                return Collections.emptyList();

-            }

-            throw new MockitoException("Cannot extract extra-interfaces from '" + typeVariable + "' : '" + type + "'");

-        }

-

-        /**

-         * @return Returns an array with the extracted raw types of {@link #extraInterfaces()}.

-         * @see #extractRawTypeOf(java.lang.reflect.Type)

-         */

-        public Class<?>[] rawExtraInterfaces() {

-            List<Type> extraInterfaces = extraInterfaces();

-            List<Class<?>> rawExtraInterfaces = new ArrayList<Class<?>>();

-            for (Type extraInterface : extraInterfaces) {

-                Class<?> rawInterface = extractRawTypeOf(extraInterface);

-                // avoid interface collision with actual raw type (with typevariables, resolution ca be quite aggressive)

-                if(!rawType().equals(rawInterface)) {

-                    rawExtraInterfaces.add(rawInterface);

-                }

-            }

-            return rawExtraInterfaces.toArray(new Class[rawExtraInterfaces.size()]);

-        }

-

-        private Type extractActualBoundedTypeOf(Type type) {

-            if (type instanceof TypeVariable) {

-                /*

-                If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared

-                on the class definition, such as such as List<E>.

-                */

-                return extractActualBoundedTypeOf(contextualActualTypeParameters.get(type));

-            }

-            if (type instanceof BoundedType) {

-                Type actualFirstBound = extractActualBoundedTypeOf(((BoundedType) type).firstBound());

-                if (!(actualFirstBound instanceof BoundedType)) {

-                    return type; // avoid going one step further, ie avoid : O(TypeVar) -> K(TypeVar) -> Some ParamType

-                }

-                return actualFirstBound;

-            }

-            return type; // irrelevant, we don't manage other types as they are not bounded.

-        }

-    }

-

-

-

-    /**

-     * Non-Generic metadata for {@link Class} returned via {@link Method#getGenericReturnType()}.

-     */

-    private static class NotGenericReturnTypeSupport extends GenericMetadataSupport {

-        private final Class<?> returnType;

-

-        public NotGenericReturnTypeSupport(Type genericReturnType) {

-            returnType = (Class<?>) genericReturnType;

-        }

-

-        @Override

-        public Class<?> rawType() {

-            return returnType;

-        }

-    }

-

-

-

-    /**

-     * Type representing bounds of a type

-     *

-     * @see TypeVarBoundedType

-     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>

-     * @see WildCardBoundedType

-     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1</a>

-     */

-    public interface BoundedType extends Type {

-        Type firstBound();

-

-        Type[] interfaceBounds();

-    }

-

-    /**

-     * Type representing bounds of a type variable, allows to keep all bounds information.

-     *

-     * <p>It uses the first bound in the array, as this array is never null and always contains at least

-     * one element (Object is always here if no bounds are declared).</p>

-     *

-     * <p>If upper bounds are declared with SomeClass and additional interfaces, then firstBound will be SomeClass and

-     * interfacesBound will be an array of the additional interfaces.

-     *

-     * i.e. <code>SomeClass</code>.

-     * <pre class="code"><code class="java">

-     *     interface UpperBoundedTypeWithClass<E extends Comparable<E> & Cloneable> {

-     *         E get();

-     *     }

-     *     // will return Comparable type

-     * </code></pre>

-     * </p>

-     *

-     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>

-     */

-    public static class TypeVarBoundedType implements BoundedType {

-        private final TypeVariable typeVariable;

-

-

-        public TypeVarBoundedType(TypeVariable typeVariable) {

-            this.typeVariable = typeVariable;

-        }

-

-        /**

-         * @return either a class or an interface (parameterized or not), if no bounds declared Object is returned.

-         */

-        public Type firstBound() {

-            return typeVariable.getBounds()[0]; //

-        }

-

-        /**

-         * On a Type Variable (typeVar extends C_0 & I_1 & I_2 & etc), will return an array

-         * containing I_1 and I_2.

-         *

-         * @return other bounds for this type, these bounds can only be only interfaces as the JLS says,

-         * empty array if no other bound declared.

-         */

-        public Type[] interfaceBounds() {

-            Type[] interfaceBounds = new Type[typeVariable.getBounds().length - 1];

-            System.arraycopy(typeVariable.getBounds(), 1, interfaceBounds, 0, typeVariable.getBounds().length - 1);

-            return interfaceBounds;

-        }

-

-        @Override

-        public boolean equals(Object o) {

-            if (this == o) return true;

-            if (o == null || getClass() != o.getClass()) return false;

-

-            return typeVariable.equals(((TypeVarBoundedType) o).typeVariable);

-

-        }

-

-        @Override

-        public int hashCode() {

-            return typeVariable.hashCode();

-        }

-

-        @Override

-        public String toString() {

-            return "{firstBound=" + firstBound() + ", interfaceBounds=" + Arrays.deepToString(interfaceBounds()) + '}';

-        }

-

-        public TypeVariable typeVariable() {

-            return typeVariable;

-        }

-    }

-

-    /**

-     * Type representing bounds of a wildcard, allows to keep all bounds information.

-     *

-     * <p>The JLS says that lower bound and upper bound are mutually exclusive, and that multiple bounds

-     * are not allowed.

-     *

-     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>

-     */

-    public static class WildCardBoundedType implements BoundedType {

-        private final WildcardType wildcard;

-

-

-        public WildCardBoundedType(WildcardType wildcard) {

-            this.wildcard = wildcard;

-        }

-

-        /**

-         * @return The first bound, either a type or a reference to a TypeVariable

-         */

-        public Type firstBound() {

-            Type[] lowerBounds = wildcard.getLowerBounds();

-            Type[] upperBounds = wildcard.getUpperBounds();

-

-            return lowerBounds.length != 0 ? lowerBounds[0] : upperBounds[0];

-        }

-

-        /**

-         * @return An empty array as, wildcard don't support multiple bounds.

-         */

-        public Type[] interfaceBounds() {

-            return new Type[0];

-        }

-

-        @Override

-        public boolean equals(Object o) {

-            if (this == o) return true;

-            if (o == null || getClass() != o.getClass()) return false;

-

-            return wildcard.equals(((TypeVarBoundedType) o).typeVariable);

-

-        }

-

-        @Override

-        public int hashCode() {

-            return wildcard.hashCode();

-        }

-

-        @Override

-        public String toString() {

-            return "{firstBound=" + firstBound() + ", interfaceBounds=[]}";

-        }

-

-        public WildcardType wildCard() {

-            return wildcard;

-        }

-    }

-

-}

-

-

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.Checks;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+
+/**
+ * This class can retrieve generic meta-data that the compiler stores on classes
+ * and accessible members.
+ *
+ * <p>
+ *     The main idea of this code is to create a Map that will help to resolve return types.
+ *     In order to actually work with nested generics, this map will have to be passed along new instances
+ *     as a type context.
+ * </p>
+ *
+ * <p>
+ *     Hence :
+ *     <ul>
+ *         <li>A new instance representing the metadata is created using the {@link #inferFrom(Type)} method from a real
+ *         <code>Class</code> or from a <code>ParameterizedType</code>, other types are not yet supported.</li>
+ *
+ *         <li>Then from this metadata, we can extract meta-data for a generic return type of a method, using
+ *         {@link #resolveGenericReturnType(Method)}.</li>
+ *     </ul>
+ * </p>
+ *
+ * <p>
+ * For now this code support the following kind of generic declarations :
+ * <pre class="code"><code class="java">
+ * interface GenericsNest&lt;K extends Comparable&lt;K&gt; & Cloneable&gt; extends Map&lt;K, Set&lt;Number&gt;&gt; {
+ *     Set&lt;Number&gt; remove(Object key); // override with fixed ParameterizedType
+ *     List&lt;? super Integer&gt; returning_wildcard_with_class_lower_bound();
+ *     List&lt;? super K&gt; returning_wildcard_with_typeVar_lower_bound();
+ *     List&lt;? extends K&gt; returning_wildcard_with_typeVar_upper_bound();
+ *     K returningK();
+ *     &lt;O extends K&gt; List&lt;O&gt; paramType_with_type_params();
+ *     &lt;S, T extends S&gt; T two_type_params();
+ *     &lt;O extends K&gt; O typeVar_with_type_params();
+ *     Number returningNonGeneric();
+ * }
+ * </code></pre>
+ *
+ * @see #inferFrom(Type)
+ * @see #resolveGenericReturnType(Method)
+ * @see org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs
+ */
+public abstract class GenericMetadataSupport {
+
+    // public static MockitoLogger logger = new ConsoleMockitoLogger();
+
+    /**
+     * Represents actual type variables resolved for current class.
+     */
+    protected Map<TypeVariable<?>, Type> contextualActualTypeParameters = new HashMap<TypeVariable<?>, Type>();
+
+    /**
+     * Registers the type variables for the given type and all of its superclasses and superinterfaces.
+     */
+    protected void registerAllTypeVariables(Type classType) {
+        Queue<Type> typesToRegister = new LinkedList<Type>();
+        Set<Type> registeredTypes = new HashSet<Type>();
+        typesToRegister.add(classType);
+
+        while (!typesToRegister.isEmpty()) {
+            Type typeToRegister = typesToRegister.poll();
+            if (typeToRegister == null || registeredTypes.contains(typeToRegister)) {
+                continue;
+            }
+
+            registerTypeVariablesOn(typeToRegister);
+            registeredTypes.add(typeToRegister);
+
+            Class<?> rawType = extractRawTypeOf(typeToRegister);
+            typesToRegister.add(rawType.getGenericSuperclass());
+            typesToRegister.addAll(Arrays.asList(rawType.getGenericInterfaces()));
+        }
+    }
+
+    protected Class<?> extractRawTypeOf(Type type) {
+        if (type instanceof Class) {
+            return (Class<?>) type;
+        }
+        if (type instanceof ParameterizedType) {
+            return (Class<?>) ((ParameterizedType) type).getRawType();
+        }
+        if (type instanceof BoundedType) {
+            return extractRawTypeOf(((BoundedType) type).firstBound());
+        }
+        if (type instanceof TypeVariable) {
+            /*
+             * If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared
+             * on the class definition, such as such as List<E>.
+             */
+            return extractRawTypeOf(contextualActualTypeParameters.get(type));
+        }
+        throw new MockitoException("Raw extraction not supported for : '" + type + "'");
+    }
+
+    protected void registerTypeVariablesOn(Type classType) {
+        if (!(classType instanceof ParameterizedType)) {
+            return;
+        }
+        ParameterizedType parameterizedType = (ParameterizedType) classType;
+        TypeVariable<?>[] typeParameters = ((Class<?>) parameterizedType.getRawType()).getTypeParameters();
+        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+        for (int i = 0; i < actualTypeArguments.length; i++) {
+            TypeVariable<?> typeParameter = typeParameters[i];
+            Type actualTypeArgument = actualTypeArguments[i];
+
+            if (actualTypeArgument instanceof WildcardType) {
+                contextualActualTypeParameters.put(typeParameter, boundsOf((WildcardType) actualTypeArgument));
+            } else if (typeParameter != actualTypeArgument) {
+                contextualActualTypeParameters.put(typeParameter, actualTypeArgument);
+            }
+            // logger.log("For '" + parameterizedType + "' found type variable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualTypeArgument + "(" + System.identityHashCode(typeParameter) + ")" + "' }");
+        }
+    }
+
+    protected void registerTypeParametersOn(TypeVariable<?>[] typeParameters) {
+        for (TypeVariable<?> type : typeParameters) {
+            registerTypeVariableIfNotPresent(type);
+        }
+    }
+
+    private void registerTypeVariableIfNotPresent(TypeVariable<?> typeVariable) {
+        if (!contextualActualTypeParameters.containsKey(typeVariable)) {
+            contextualActualTypeParameters.put(typeVariable, boundsOf(typeVariable));
+            // logger.log("For '" + typeVariable.getGenericDeclaration() + "' found type variable : { '" + typeVariable + "(" + System.identityHashCode(typeVariable) + ")" + "' : '" + boundsOf(typeVariable) + "' }");
+        }
+    }
+
+    /**
+     * @param typeParameter The TypeVariable parameter
+     * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable
+     *         then retrieve BoundedType of this TypeVariable
+     */
+    private BoundedType boundsOf(TypeVariable<?> typeParameter) {
+        if (typeParameter.getBounds()[0] instanceof TypeVariable) {
+            return boundsOf((TypeVariable<?>) typeParameter.getBounds()[0]);
+        }
+        return new TypeVarBoundedType(typeParameter);
+    }
+
+    /**
+     * @param wildCard The WildCard type
+     * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable
+     *         then retrieve BoundedType of this TypeVariable
+     */
+    private BoundedType boundsOf(WildcardType wildCard) {
+        /*
+         *  According to JLS(http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1):
+         *  - Lower and upper can't coexist: (for instance, this is not allowed: <? extends List<String> & super MyInterface>)
+         *  - Multiple bounds are not supported (for instance, this is not allowed: <? extends List<String> & MyInterface>)
+         */
+
+        WildCardBoundedType wildCardBoundedType = new WildCardBoundedType(wildCard);
+        if (wildCardBoundedType.firstBound() instanceof TypeVariable) {
+            return boundsOf((TypeVariable<?>) wildCardBoundedType.firstBound());
+        }
+
+        return wildCardBoundedType;
+    }
+
+    /**
+     * @return Raw type of the current instance.
+     */
+    public abstract Class<?> rawType();
+
+    /**
+     * @return Returns extra interfaces <strong>if relevant</strong>, otherwise empty List.
+     */
+    public List<Type> extraInterfaces() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * @return Returns an array with the raw types of {@link #extraInterfaces()} <strong>if relevant</strong>.
+     */
+    public Class<?>[] rawExtraInterfaces() {
+        return new Class[0];
+    }
+
+    /**
+     * @return Returns true if metadata knows about extra-interfaces {@link #extraInterfaces()} <strong>if relevant</strong>.
+     */
+    public boolean hasRawExtraInterfaces() {
+        return rawExtraInterfaces().length > 0;
+    }
+
+    /**
+     * @return Actual type arguments matching the type variables of the raw type represented by this {@link GenericMetadataSupport} instance.
+     */
+    public Map<TypeVariable<?>, Type> actualTypeArguments() {
+        TypeVariable<?>[] typeParameters = rawType().getTypeParameters();
+        LinkedHashMap<TypeVariable<?>, Type> actualTypeArguments = new LinkedHashMap<TypeVariable<?>, Type>();
+
+        for (TypeVariable<?> typeParameter : typeParameters) {
+
+            Type actualType = getActualTypeArgumentFor(typeParameter);
+
+            actualTypeArguments.put(typeParameter, actualType);
+            // logger.log("For '" + rawType().getCanonicalName() + "' returning explicit TypeVariable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualType +"' }");
+        }
+
+        return actualTypeArguments;
+    }
+
+    protected Type getActualTypeArgumentFor(TypeVariable<?> typeParameter) {
+        Type type = this.contextualActualTypeParameters.get(typeParameter);
+        if (type instanceof TypeVariable) {
+            TypeVariable<?> typeVariable = (TypeVariable<?>) type;
+            return getActualTypeArgumentFor(typeVariable);
+        }
+
+        return type;
+    }
+
+    /**
+     * Resolve current method generic return type to a {@link GenericMetadataSupport}.
+     *
+     * @param method Method to resolve the return type.
+     * @return {@link GenericMetadataSupport} representing this generic return type.
+     */
+    public GenericMetadataSupport resolveGenericReturnType(Method method) {
+        Type genericReturnType = method.getGenericReturnType();
+        // logger.log("Method '" + method.toGenericString() + "' has return type : " + genericReturnType.getClass().getInterfaces()[0].getSimpleName() + " : " + genericReturnType);
+
+        int arity = 0;
+        while(genericReturnType instanceof GenericArrayType) {
+            arity++;
+            genericReturnType = ((GenericArrayType) genericReturnType).getGenericComponentType();
+        }
+
+        GenericMetadataSupport genericMetadataSupport = resolveGenericType(genericReturnType, method);
+        if (arity == 0) {
+            return genericMetadataSupport;
+        } else {
+            return new GenericArrayReturnType(genericMetadataSupport, arity);
+        }
+    }
+
+    private GenericMetadataSupport resolveGenericType(Type type, Method method) {
+
+        if (type instanceof Class) {
+            return new NotGenericReturnTypeSupport(this, type);
+        }
+        if (type instanceof ParameterizedType) {
+            return new ParameterizedReturnType(this, method.getTypeParameters(), (ParameterizedType) type);
+        }
+        if (type instanceof TypeVariable) {
+            return new TypeVariableReturnType(this, method.getTypeParameters(), (TypeVariable<?>) type);
+        }
+
+        throw new MockitoException("Ouch, it shouldn't happen, type '" + type.getClass().getCanonicalName() + "' on method : '" + method.toGenericString() + "' is not supported : " + type);
+    }
+
+    /**
+     * Create an new instance of {@link GenericMetadataSupport} inferred from a {@link Type}.
+     *
+     * <p>
+     *     At the moment <code>type</code> can only be a {@link Class} or a {@link ParameterizedType}, otherwise
+     *     it'll throw a {@link MockitoException}.
+     * </p>
+     *
+     * @param type The class from which the {@link GenericMetadataSupport} should be built.
+     * @return The new {@link GenericMetadataSupport}.
+     * @throws MockitoException Raised if type is not a {@link Class} or a {@link ParameterizedType}.
+     */
+    public static GenericMetadataSupport inferFrom(Type type) {
+        Checks.checkNotNull(type, "type");
+        if (type instanceof Class) {
+            return new FromClassGenericMetadataSupport((Class<?>) type);
+        }
+        if (type instanceof ParameterizedType) {
+            return new FromParameterizedTypeGenericMetadataSupport((ParameterizedType) type);
+        }
+
+        throw new MockitoException("Type meta-data for this Type (" + type.getClass().getCanonicalName() + ") is not supported : " + type);
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    //// Below are specializations of GenericMetadataSupport that could handle retrieval of possible Types
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Generic metadata implementation for {@link Class}.
+     *
+     * Offer support to retrieve generic metadata on a {@link Class} by reading type parameters and type variables on
+     * the class and its ancestors and interfaces.
+     */
+    private static class FromClassGenericMetadataSupport extends GenericMetadataSupport {
+        private final Class<?> clazz;
+
+        public FromClassGenericMetadataSupport(Class<?> clazz) {
+            this.clazz = clazz;
+
+            registerTypeParametersOn(clazz.getTypeParameters());
+            registerAllTypeVariables(clazz);
+        }
+
+        @Override
+        public Class<?> rawType() {
+            return clazz;
+        }
+    }
+
+    /**
+     * Generic metadata implementation for "standalone" {@link ParameterizedType}.
+     *
+     * Offer support to retrieve generic metadata on a {@link ParameterizedType} by reading type variables of
+     * the related raw type and declared type variable of this parameterized type.
+     *
+     * This class is not designed to work on ParameterizedType returned by {@link Method#getGenericReturnType()}, as
+     * the ParameterizedType instance return in these cases could have Type Variables that refer to type declaration(s).
+     * That's what meant the "standalone" word at the beginning of the Javadoc.
+     * Instead use {@link ParameterizedReturnType}.
+     */
+    private static class FromParameterizedTypeGenericMetadataSupport extends GenericMetadataSupport {
+        private final ParameterizedType parameterizedType;
+
+        public FromParameterizedTypeGenericMetadataSupport(ParameterizedType parameterizedType) {
+            this.parameterizedType = parameterizedType;
+            readActualTypeParameters();
+        }
+
+        private void readActualTypeParameters() {
+            registerAllTypeVariables(parameterizedType);
+        }
+
+        @Override
+        public Class<?> rawType() {
+            return (Class<?>) parameterizedType.getRawType();
+        }
+    }
+
+    /**
+     * Generic metadata specific to {@link ParameterizedType} returned via {@link Method#getGenericReturnType()}.
+     */
+    private static class ParameterizedReturnType extends GenericMetadataSupport {
+        private final ParameterizedType parameterizedType;
+        private final TypeVariable<?>[] typeParameters;
+
+        public ParameterizedReturnType(GenericMetadataSupport source, TypeVariable<?>[] typeParameters, ParameterizedType parameterizedType) {
+            this.parameterizedType = parameterizedType;
+            this.typeParameters = typeParameters;
+            this.contextualActualTypeParameters = source.contextualActualTypeParameters;
+
+            readTypeParameters();
+            readTypeVariables();
+        }
+
+        private void readTypeParameters() {
+            registerTypeParametersOn(typeParameters);
+        }
+
+        private void readTypeVariables() {
+            registerTypeVariablesOn(parameterizedType);
+        }
+
+        @Override
+        public Class<?> rawType() {
+            return (Class<?>) parameterizedType.getRawType();
+        }
+
+    }
+
+    /**
+     * Generic metadata for {@link TypeVariable} returned via {@link Method#getGenericReturnType()}.
+     */
+    private static class TypeVariableReturnType extends GenericMetadataSupport {
+        private final TypeVariable<?> typeVariable;
+        private final TypeVariable<?>[] typeParameters;
+        private Class<?> rawType;
+
+        public TypeVariableReturnType(GenericMetadataSupport source, TypeVariable<?>[] typeParameters, TypeVariable<?> typeVariable) {
+            this.typeParameters = typeParameters;
+            this.typeVariable = typeVariable;
+            this.contextualActualTypeParameters = source.contextualActualTypeParameters;
+
+            readTypeParameters();
+            readTypeVariables();
+        }
+
+        private void readTypeParameters() {
+            registerTypeParametersOn(typeParameters);
+        }
+
+        private void readTypeVariables() {
+            for (Type type : typeVariable.getBounds()) {
+                registerTypeVariablesOn(type);
+            }
+            registerTypeParametersOn(new TypeVariable[] { typeVariable });
+            registerTypeVariablesOn(getActualTypeArgumentFor(typeVariable));
+        }
+
+        @Override
+        public Class<?> rawType() {
+            if (rawType == null) {
+                rawType = extractRawTypeOf(typeVariable);
+            }
+            return rawType;
+        }
+
+        @Override
+        public List<Type> extraInterfaces() {
+            Type type = extractActualBoundedTypeOf(typeVariable);
+            if (type instanceof BoundedType) {
+                return Arrays.asList(((BoundedType) type).interfaceBounds());
+            }
+            if (type instanceof ParameterizedType) {
+                return Collections.singletonList(type);
+            }
+            if (type instanceof Class) {
+                return Collections.emptyList();
+            }
+            throw new MockitoException("Cannot extract extra-interfaces from '" + typeVariable + "' : '" + type + "'");
+        }
+
+        /**
+         * @return Returns an array with the extracted raw types of {@link #extraInterfaces()}.
+         * @see #extractRawTypeOf(java.lang.reflect.Type)
+         */
+        public Class<?>[] rawExtraInterfaces() {
+            List<Type> extraInterfaces = extraInterfaces();
+            List<Class<?>> rawExtraInterfaces = new ArrayList<Class<?>>();
+            for (Type extraInterface : extraInterfaces) {
+                Class<?> rawInterface = extractRawTypeOf(extraInterface);
+                // avoid interface collision with actual raw type (with typevariables, resolution ca be quite aggressive)
+                if(!rawType().equals(rawInterface)) {
+                    rawExtraInterfaces.add(rawInterface);
+                }
+            }
+            return rawExtraInterfaces.toArray(new Class[rawExtraInterfaces.size()]);
+        }
+
+        private Type extractActualBoundedTypeOf(Type type) {
+            if (type instanceof TypeVariable) {
+                /*
+                If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared
+                on the class definition, such as such as List<E>.
+                */
+                return extractActualBoundedTypeOf(contextualActualTypeParameters.get(type));
+            }
+            if (type instanceof BoundedType) {
+                Type actualFirstBound = extractActualBoundedTypeOf(((BoundedType) type).firstBound());
+                if (!(actualFirstBound instanceof BoundedType)) {
+                    return type; // avoid going one step further, ie avoid : O(TypeVar) -> K(TypeVar) -> Some ParamType
+                }
+                return actualFirstBound;
+            }
+            return type; // irrelevant, we don't manage other types as they are not bounded.
+        }
+    }
+
+    private static class GenericArrayReturnType extends GenericMetadataSupport {
+
+        private final GenericMetadataSupport genericArrayType;
+
+        private final int arity;
+
+        public GenericArrayReturnType(GenericMetadataSupport genericArrayType, int arity) {
+            this.genericArrayType = genericArrayType;
+            this.arity = arity;
+        }
+
+        @Override
+        public Class<?> rawType() {
+            Class<?> rawComponentType = genericArrayType.rawType();
+            StringBuilder stringBuilder = new StringBuilder();
+            for (int i = 0; i < arity; i++) {
+                stringBuilder.append("[");
+            }
+            try {
+                return Class.forName(stringBuilder.append("L").append(rawComponentType.getName()).append(";").toString(), false, rawComponentType.getClassLoader());
+            } catch (ClassNotFoundException e) {
+                throw new IllegalStateException("This was not supposed to happend", e);
+            }
+        }
+    }
+
+    /**
+     * Non-Generic metadata for {@link Class} returned via {@link Method#getGenericReturnType()}.
+     */
+    private static class NotGenericReturnTypeSupport extends GenericMetadataSupport {
+        private final Class<?> returnType;
+
+        public NotGenericReturnTypeSupport(GenericMetadataSupport source, Type genericReturnType) {
+            returnType = (Class<?>) genericReturnType;
+            this.contextualActualTypeParameters = source.contextualActualTypeParameters;
+
+            registerAllTypeVariables(returnType);
+        }
+
+        @Override
+        public Class<?> rawType() {
+            return returnType;
+        }
+    }
+
+
+
+    /**
+     * Type representing bounds of a type
+     *
+     * @see TypeVarBoundedType
+     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>
+     * @see WildCardBoundedType
+     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1</a>
+     */
+    public interface BoundedType extends Type {
+        Type firstBound();
+
+        Type[] interfaceBounds();
+    }
+
+    /**
+     * Type representing bounds of a type variable, allows to keep all bounds information.
+     *
+     * <p>It uses the first bound in the array, as this array is never null and always contains at least
+     * one element (Object is always here if no bounds are declared).</p>
+     *
+     * <p>If upper bounds are declared with SomeClass and additional interfaces, then firstBound will be SomeClass and
+     * interfacesBound will be an array of the additional interfaces.
+     *
+     * i.e. <code>SomeClass</code>.
+     * <pre class="code"><code class="java">
+     *     interface UpperBoundedTypeWithClass<E extends Comparable<E> & Cloneable> {
+     *         E get();
+     *     }
+     *     // will return Comparable type
+     * </code></pre>
+     * </p>
+     *
+     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>
+     */
+    public static class TypeVarBoundedType implements BoundedType {
+        private final TypeVariable<?> typeVariable;
+
+        public TypeVarBoundedType(TypeVariable<?> typeVariable) {
+            this.typeVariable = typeVariable;
+        }
+
+        /**
+         * @return either a class or an interface (parameterized or not), if no bounds declared Object is returned.
+         */
+        public Type firstBound() {
+            return typeVariable.getBounds()[0]; //
+        }
+
+        /**
+         * On a Type Variable (typeVar extends C_0 & I_1 & I_2 & etc), will return an array
+         * containing I_1 and I_2.
+         *
+         * @return other bounds for this type, these bounds can only be only interfaces as the JLS says,
+         * empty array if no other bound declared.
+         */
+        public Type[] interfaceBounds() {
+            Type[] interfaceBounds = new Type[typeVariable.getBounds().length - 1];
+            System.arraycopy(typeVariable.getBounds(), 1, interfaceBounds, 0, typeVariable.getBounds().length - 1);
+            return interfaceBounds;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            return typeVariable.equals(((TypeVarBoundedType) o).typeVariable);
+
+        }
+
+        @Override
+        public int hashCode() {
+            return typeVariable.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return "{firstBound=" + firstBound() + ", interfaceBounds=" + Arrays.deepToString(interfaceBounds()) + '}';
+        }
+
+        public TypeVariable<?> typeVariable() {
+            return typeVariable;
+        }
+    }
+
+    /**
+     * Type representing bounds of a wildcard, allows to keep all bounds information.
+     *
+     * <p>The JLS says that lower bound and upper bound are mutually exclusive, and that multiple bounds
+     * are not allowed.
+     *
+     * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>
+     */
+    public static class WildCardBoundedType implements BoundedType {
+        private final WildcardType wildcard;
+
+
+        public WildCardBoundedType(WildcardType wildcard) {
+            this.wildcard = wildcard;
+        }
+
+        /**
+         * @return The first bound, either a type or a reference to a TypeVariable
+         */
+        public Type firstBound() {
+            Type[] lowerBounds = wildcard.getLowerBounds();
+            Type[] upperBounds = wildcard.getUpperBounds();
+
+            return lowerBounds.length != 0 ? lowerBounds[0] : upperBounds[0];
+        }
+
+        /**
+         * @return An empty array as, wildcard don't support multiple bounds.
+         */
+        public Type[] interfaceBounds() {
+            return new Type[0];
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            return wildcard.equals(((TypeVarBoundedType) o).typeVariable);
+
+        }
+
+        @Override
+        public int hashCode() {
+            return wildcard.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return "{firstBound=" + firstBound() + ", interfaceBounds=[]}";
+        }
+
+        public WildcardType wildCard() {
+            return wildcard;
+        }
+    }
+
+}
+
+
diff --git a/src/main/java/org/mockito/internal/util/reflection/GenericTypeExtractor.java b/src/main/java/org/mockito/internal/util/reflection/GenericTypeExtractor.java
new file mode 100644
index 0000000..cad1715
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/reflection/GenericTypeExtractor.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Attempts to extract generic type of given target base class or target interface
+ */
+public class GenericTypeExtractor {
+
+    /**
+     * Extract generic type of root class either from the target base class or from target base interface.
+     * Examples:
+     *  <p>
+     *  1. Foo implements IFoo[Integer]:
+     *      genericTypeOf(Foo.class, Object.class, IFoo.class) returns Integer
+     *  <p>
+     *  2. Foo extends BaseFoo[String]:
+     *      genericTypeOf(Foo.class, BaseFoo.class, IFoo.class) returns String
+     *  <p>
+     *  3. Foo extends BaseFoo; BaseFoo implements IFoo[String]:
+     *      genericTypeOf(Foo.class, BaseFoo.class, Object.class) returns String
+     *  <p>
+     *  Does not support nested generics, only supports single type parameter.
+     *
+     * @param rootClass - the root class that the search begins from
+     * @param targetBaseClass - if one of the classes in the root class' hierarchy extends this base class
+     *                        it will be used for generic type extraction
+     * @param targetBaseInterface - if one of the interfaces in the root class' hierarchy implements this interface
+     *                            it will be used for generic type extraction
+     * @return generic interface if found, Object.class if not found.
+     */
+    public static Class<?> genericTypeOf(Class<?> rootClass, Class<?> targetBaseClass, Class<?> targetBaseInterface) {
+        //looking for candidates in the hierarchy of rootClass
+        Class<?> match = rootClass;
+        while(match != Object.class) {
+            //check the super class first
+            if (match.getSuperclass() == targetBaseClass) {
+                return extractGeneric(match.getGenericSuperclass());
+            }
+            //check the interfaces (recursively)
+            Type genericInterface = findGenericInteface(match, targetBaseInterface);
+            if (genericInterface != null) {
+                return extractGeneric(genericInterface);
+            }
+            //recurse the hierarchy
+            match = match.getSuperclass();
+        }
+        return Object.class;
+    }
+
+    /**
+     * Finds generic interface implementation based on the source class and the target interface.
+     * Returns null if not found. Recurses the interface hierarchy.
+     */
+    private static Type findGenericInteface(Class<?> sourceClass, Class<?> targetBaseInterface) {
+        for (int i = 0; i < sourceClass.getInterfaces().length; i++) {
+            Class<?> inter = sourceClass.getInterfaces()[i];
+            if (inter == targetBaseInterface) {
+                return sourceClass.getGenericInterfaces()[0];
+            } else {
+                Type deeper = findGenericInteface(inter, targetBaseInterface);
+                if (deeper != null) {
+                    return deeper;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Attempts to extract generic parameter type of given type.
+     * If there is no generic parameter it returns Object.class
+     */
+    private static Class<?> extractGeneric(Type type) {
+        if (type instanceof ParameterizedType) {
+            Type[] genericTypes = ((ParameterizedType) type).getActualTypeArguments();
+            if (genericTypes.length > 0 && genericTypes[0] instanceof Class) {
+                return (Class<?>) genericTypes[0];
+            }
+        }
+        return Object.class;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/InstanceField.java b/src/main/java/org/mockito/internal/util/reflection/InstanceField.java
index c3f019d..8756e6a 100644
--- a/src/main/java/org/mockito/internal/util/reflection/InstanceField.java
+++ b/src/main/java/org/mockito/internal/util/reflection/InstanceField.java
@@ -6,6 +6,8 @@
 
 import org.mockito.internal.util.Checks;
 
+import static org.mockito.internal.util.reflection.FieldSetter.setField;
+
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 
@@ -48,7 +50,7 @@
      * @see FieldSetter
      */
     public void set(Object value) {
-        new FieldSetter(instance, field).set(value);
+        setField(instance, field,value);
     }
 
     /**
@@ -71,6 +73,15 @@
     }
 
     /**
+     * Check if the field is synthetic.
+     *
+     * @return <code>true</code> if the field is synthetic, else <code>false</code>.
+     */
+    public boolean isSynthetic() {
+        return field.isSynthetic();
+    }
+
+    /**
      * Returns the annotation instance for the given annotation type.
      *
      * @param annotationClass Tha annotation type to retrieve.
@@ -107,6 +118,11 @@
     }
 
     @Override
+    public String toString() {
+        return name();
+    }
+
+    @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
diff --git a/src/main/java/org/mockito/internal/util/reflection/LenientCopyTool.java b/src/main/java/org/mockito/internal/util/reflection/LenientCopyTool.java
index 2418ced..c6b9919 100644
--- a/src/main/java/org/mockito/internal/util/reflection/LenientCopyTool.java
+++ b/src/main/java/org/mockito/internal/util/reflection/LenientCopyTool.java
@@ -2,49 +2,48 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.Field;

-import java.lang.reflect.Modifier;

-

-@SuppressWarnings("unchecked")

-public class LenientCopyTool {

-

-    FieldCopier fieldCopier = new FieldCopier();

-

-    public <T> void copyToMock(T from, T mock) {

-        copy(from, mock, from.getClass(), mock.getClass().getSuperclass());

-    }

-

-    public <T> void copyToRealObject(T from, T to) {

-        copy(from, to, from.getClass(), to.getClass());

-    }

-

-    private <T> void copy(T from, T to, Class fromClazz, Class toClass) {

-        while (fromClazz != Object.class) {

-            copyValues(from, to, fromClazz);

-            fromClazz = fromClazz.getSuperclass();

-        }

-    }

-

-    private <T> void copyValues(T from, T mock, Class classFrom) {

-        Field[] fields = classFrom.getDeclaredFields();

-

-        for (int i = 0; i < fields.length; i++) {

-            // ignore static fields

-            Field field = fields[i];

-            if (Modifier.isStatic(field.getModifiers())) {

-                continue;

-            }

-            AccessibilityChanger accessibilityChanger = new AccessibilityChanger();

-            try {

-                accessibilityChanger.enableAccess(field);

-                fieldCopier.copyValue(from, mock, field);

-            } catch (Throwable t) {

-                //Ignore - be lenient - if some field cannot be copied then let's be it

-            } finally {

-                accessibilityChanger.safelyDisableAccess(field);

-            }

-        }

-    }

-}
\ No newline at end of file
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+@SuppressWarnings("unchecked")
+public class LenientCopyTool {
+
+    FieldCopier fieldCopier = new FieldCopier();
+
+    public <T> void copyToMock(T from, T mock) {
+        copy(from, mock, from.getClass());
+    }
+
+    public <T> void copyToRealObject(T from, T to) {
+        copy(from, to, from.getClass());
+    }
+
+    private <T> void copy(T from, T to, Class<?> fromClazz) {
+        while (fromClazz != Object.class) {
+            copyValues(from, to, fromClazz);
+            fromClazz = fromClazz.getSuperclass();
+        }
+    }
+
+    private <T> void copyValues(T from, T mock, Class<?> classFrom) {
+        Field[] fields = classFrom.getDeclaredFields();
+
+        for (Field field : fields) {
+            // ignore static fields
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+            AccessibilityChanger accessibilityChanger = new AccessibilityChanger();
+            try {
+                accessibilityChanger.enableAccess(field);
+                fieldCopier.copyValue(from, mock, field);
+            } catch (Throwable t) {
+                //Ignore - be lenient - if some field cannot be copied then let's be it
+            } finally {
+                accessibilityChanger.safelyDisableAccess(field);
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/SuperTypesLastSorter.java b/src/main/java/org/mockito/internal/util/reflection/SuperTypesLastSorter.java
new file mode 100644
index 0000000..8f5c161
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/reflection/SuperTypesLastSorter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Sort fields in an order suitable for injection, by name with superclasses
+ * moved after their subclasses.
+ */
+public class SuperTypesLastSorter {
+
+    private SuperTypesLastSorter() {
+    }
+
+    /**
+     * Return a new collection with the fields sorted first by name,
+     * then with any fields moved after their supertypes.
+     */
+    public static List<Field> sortSuperTypesLast(Collection<? extends Field> unsortedFields) {
+        List<Field> fields = new ArrayList<Field>(unsortedFields);
+
+        Collections.sort(fields, compareFieldsByName);
+
+        int i = 0;
+
+        while (i < fields.size() - 1) {
+            Field f = fields.get(i);
+            Class<?> ft = f.getType();
+            int newPos = i;
+            for (int j = i + 1; j < fields.size(); j++) {
+                Class<?> t = fields.get(j).getType();
+
+                if (ft != t && ft.isAssignableFrom(t)) {
+                    newPos = j;
+                }
+            }
+
+            if (newPos == i) {
+                i++;
+            } else {
+                fields.remove(i);
+                fields.add(newPos, f);
+            }
+        }
+
+        return fields;
+    }
+
+
+    private static final Comparator<Field> compareFieldsByName = new Comparator<Field>() {
+        @Override
+        public int compare(Field o1, Field o2) {
+            return o1.getName().compareTo(o2.getName());
+        }
+    };
+}
diff --git a/src/main/java/org/mockito/internal/util/reflection/Whitebox.java b/src/main/java/org/mockito/internal/util/reflection/Whitebox.java
deleted file mode 100644
index 54a7cc6..0000000
--- a/src/main/java/org/mockito/internal/util/reflection/Whitebox.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.util.reflection;

-

-import java.lang.reflect.Field;

-

-public class Whitebox {

-

-    public static Object getInternalState(Object target, String field) {

-        Class<?> c = target.getClass();

-        try {

-            Field f = getFieldFromHierarchy(c, field);

-            f.setAccessible(true);

-            return f.get(target);

-        } catch (Exception e) {

-            throw new RuntimeException("Unable to get internal state on a private field. Please report to mockito mailing list.", e);

-        }

-    }

-

-    public static void setInternalState(Object target, String field, Object value) {

-        Class<?> c = target.getClass();

-        try {

-            Field f = getFieldFromHierarchy(c, field);

-            f.setAccessible(true);

-            f.set(target, value);

-        } catch (Exception e) {

-            throw new RuntimeException("Unable to set internal state on a private field. Please report to mockito mailing list.", e);

-        }

-    }

-

-    private static Field getFieldFromHierarchy(Class<?> clazz, String field) {

-        Field f = getField(clazz, field);

-        while (f == null && clazz != Object.class) {

-            clazz = clazz.getSuperclass();

-            f = getField(clazz, field);

-        }

-        if (f == null) {

-            throw new RuntimeException(

-                    "You want me to get this field: '" + field +

-                    "' on this class: '" + clazz.getSimpleName() + 

-                    "' but this field is not declared withing hierarchy of this class!");

-        }

-        return f;

-    }

-

-    private static Field getField(Class<?> clazz, String field) {

-        try {

-            return clazz.getDeclaredField(field);

-        } catch (NoSuchFieldException e) {

-            return null;

-        }

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/util/reflection/package-info.java b/src/main/java/org/mockito/internal/util/reflection/package-info.java
new file mode 100644
index 0000000..fc166e6
--- /dev/null
+++ b/src/main/java/org/mockito/internal/util/reflection/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Reflection utilities.
+ */
+package org.mockito.internal.util.reflection;
diff --git a/src/main/java/org/mockito/internal/util/reflection/package.html b/src/main/java/org/mockito/internal/util/reflection/package.html
deleted file mode 100644
index ac2eca0..0000000
--- a/src/main/java/org/mockito/internal/util/reflection/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-reflection utilities
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/AtLeast.java b/src/main/java/org/mockito/internal/verification/AtLeast.java
index db2cbda..768cc92 100644
--- a/src/main/java/org/mockito/internal/verification/AtLeast.java
+++ b/src/main/java/org/mockito/internal/verification/AtLeast.java
@@ -5,57 +5,49 @@
 
 package org.mockito.internal.verification;
 
-import java.util.List;
+import static org.mockito.internal.verification.checkers.AtLeastXNumberOfInvocationsChecker.checkAtLeastNumberOfInvocations;
+import static org.mockito.internal.verification.checkers.MissingInvocationChecker.checkMissingInvocation;
 
 import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.invocation.InvocationMatcher;
 import org.mockito.internal.verification.api.VerificationData;
 import org.mockito.internal.verification.api.VerificationDataInOrder;
 import org.mockito.internal.verification.api.VerificationInOrderMode;
-import org.mockito.internal.verification.checkers.AtLeastXNumberOfInvocationsChecker;
-import org.mockito.internal.verification.checkers.AtLeastXNumberOfInvocationsInOrderChecker;
-import org.mockito.internal.verification.checkers.MissingInvocationChecker;
-import org.mockito.internal.verification.checkers.MissingInvocationInOrderChecker;
-import org.mockito.invocation.Invocation;
 import org.mockito.verification.VerificationMode;
 
 public class AtLeast implements VerificationInOrderMode, VerificationMode {
-    
+
     final int wantedCount;
-    
+
     public AtLeast(int wantedNumberOfInvocations) {
         if (wantedNumberOfInvocations < 0) {
             throw new MockitoException("Negative value is not allowed here");
         }
         this.wantedCount = wantedNumberOfInvocations;
     }
-    
+
+    @Override
     public void verify(VerificationData data) {
-        MissingInvocationChecker missingInvocation = new MissingInvocationChecker();
-        AtLeastXNumberOfInvocationsChecker numberOfInvocations = new AtLeastXNumberOfInvocationsChecker();
-        
         if (wantedCount == 1) {
-            missingInvocation.check(data.getAllInvocations(), data.getWanted());
+             checkMissingInvocation(data.getAllInvocations(), data.getTarget());
         }
-        numberOfInvocations.check(data.getAllInvocations(), data.getWanted(), wantedCount);
+        checkAtLeastNumberOfInvocations(data.getAllInvocations(), data.getTarget(), wantedCount);
     }
-    
+
+    @Override
     public void verifyInOrder(VerificationDataInOrder data) {
-        List<Invocation> allInvocations = data.getAllInvocations();
-        InvocationMatcher wanted = data.getWanted();
-        
-        MissingInvocationInOrderChecker missingInvocation = new MissingInvocationInOrderChecker();
-        AtLeastXNumberOfInvocationsInOrderChecker numberOfCalls = new AtLeastXNumberOfInvocationsInOrderChecker(data.getOrderingContext());
-        
         if (wantedCount == 1) {
-            missingInvocation.check(allInvocations, wanted, this, data.getOrderingContext());
+             checkMissingInvocation(data.getAllInvocations(), data.getWanted(),  data.getOrderingContext());
         }
-        
-        numberOfCalls.check(allInvocations, wanted, wantedCount);
+        checkAtLeastNumberOfInvocations(data.getAllInvocations(), data.getWanted(), wantedCount, data.getOrderingContext());
     }
 
     @Override
     public String toString() {
         return "Wanted invocations count: at least " + wantedCount;
     }
-}
\ No newline at end of file
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/AtMost.java b/src/main/java/org/mockito/internal/verification/AtMost.java
index b705a5b..d8e8ecc 100644
--- a/src/main/java/org/mockito/internal/verification/AtMost.java
+++ b/src/main/java/org/mockito/internal/verification/AtMost.java
@@ -5,13 +5,15 @@
 
 package org.mockito.internal.verification;
 
-import java.util.List;
+import static org.mockito.internal.exceptions.Reporter.wantedAtMostX;
+import static org.mockito.internal.invocation.InvocationMarker.markVerified;
+import static org.mockito.internal.invocation.InvocationsFinder.findInvocations;
 
-import org.mockito.exceptions.Reporter;
+import java.util.Iterator;
+import java.util.List;
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationMarker;
-import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.invocation.MatchableInvocation;
 import org.mockito.internal.verification.api.VerificationData;
 import org.mockito.invocation.Invocation;
 import org.mockito.verification.VerificationMode;
@@ -19,7 +21,6 @@
 public class AtMost implements VerificationMode {
 
     private final int maxNumberOfInvocations;
-    private final InvocationMarker invocationMarker = new InvocationMarker();
 
     public AtMost(int maxNumberOfInvocations) {
         if (maxNumberOfInvocations < 0) {
@@ -30,15 +31,29 @@
 
     public void verify(VerificationData data) {
         List<Invocation> invocations = data.getAllInvocations();
-        InvocationMatcher wanted = data.getWanted();
-        
-        InvocationsFinder finder = new InvocationsFinder();
-        List<Invocation> found = finder.findInvocations(invocations, wanted);
+        MatchableInvocation wanted = data.getTarget();
+
+        List<Invocation> found = findInvocations(invocations, wanted);
         int foundSize = found.size();
         if (foundSize > maxNumberOfInvocations) {
-            new Reporter().wantedAtMostX(maxNumberOfInvocations, foundSize);
+            throw wantedAtMostX(maxNumberOfInvocations, foundSize);
         }
-        
-        invocationMarker.markVerified(found, wanted);
+
+        removeAlreadyVerified(found);
+        markVerified(found, wanted);
     }
-}
\ No newline at end of file
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+
+    private void removeAlreadyVerified(List<Invocation> invocations) {
+        for (Iterator<Invocation> iterator = invocations.iterator(); iterator.hasNext(); ) {
+            Invocation i = iterator.next();
+            if (i.isVerified()) {
+                iterator.remove();
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/Calls.java b/src/main/java/org/mockito/internal/verification/Calls.java
index 5bdc604..9083752 100644
--- a/src/main/java/org/mockito/internal/verification/Calls.java
+++ b/src/main/java/org/mockito/internal/verification/Calls.java
@@ -5,17 +5,18 @@
 
 package org.mockito.internal.verification;
 
+import static org.mockito.internal.verification.checkers.MissingInvocationChecker.checkMissingInvocation;
+import static org.mockito.internal.verification.checkers.NumberOfInvocationsChecker.checkNumberOfInvocationsNonGreedy;
+
+import java.util.List;
 import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.invocation.InvocationMatcher;
 import org.mockito.internal.verification.api.VerificationData;
 import org.mockito.internal.verification.api.VerificationDataInOrder;
 import org.mockito.internal.verification.api.VerificationInOrderMode;
-import org.mockito.internal.verification.checkers.*;
 import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
 import org.mockito.verification.VerificationMode;
 
-import java.util.List;
-
 public class Calls implements VerificationMode, VerificationInOrderMode {
 
     final int wantedCount;
@@ -27,23 +28,27 @@
         this.wantedCount = wantedNumberOfInvocations;
     }
 
+    @Override
     public void verify(VerificationData data) {
         throw new MockitoException( "calls is only intended to work with InOrder" );
     }
 
+    @Override
     public void verifyInOrder(VerificationDataInOrder data) {
         List<Invocation> allInvocations = data.getAllInvocations();
-        InvocationMatcher wanted = data.getWanted();
-        
-        MissingInvocationInOrderChecker missingInvocation = new MissingInvocationInOrderChecker();
-        missingInvocation.check( allInvocations, wanted, this, data.getOrderingContext());
-        NonGreedyNumberOfInvocationsInOrderChecker numberOfCalls = new NonGreedyNumberOfInvocationsInOrderChecker();
-        numberOfCalls.check( allInvocations, wanted, wantedCount, data.getOrderingContext());
-    }    
-    
+        MatchableInvocation wanted = data.getWanted();
+
+        checkMissingInvocation(allInvocations, wanted,  data.getOrderingContext());
+        checkNumberOfInvocationsNonGreedy(allInvocations, wanted, wantedCount, data.getOrderingContext());
+    }
+
     @Override
     public String toString() {
         return "Wanted invocations count (non-greedy): " + wantedCount;
     }
 
-}
\ No newline at end of file
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/DefaultRegisteredInvocations.java b/src/main/java/org/mockito/internal/verification/DefaultRegisteredInvocations.java
index 5ad9338..6841882 100644
--- a/src/main/java/org/mockito/internal/verification/DefaultRegisteredInvocations.java
+++ b/src/main/java/org/mockito/internal/verification/DefaultRegisteredInvocations.java
@@ -10,6 +10,8 @@
 import org.mockito.internal.util.collections.ListUtil.Filter;
 import org.mockito.invocation.Invocation;
 
+import static org.mockito.internal.util.ObjectMethodsGuru.isToStringMethod;
+
 import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
@@ -36,14 +38,20 @@
     }
 
     public List<Invocation> getAll() {
-    	List<Invocation> copiedList;
-    	synchronized (invocations) {
-			copiedList = new LinkedList<Invocation>(invocations) ;
-		}
+        List<Invocation> copiedList;
+        synchronized (invocations) {
+            copiedList = new LinkedList<Invocation>(invocations) ;
+        }
 
         return ListUtil.filter(copiedList, new RemoveToString());
     }
 
+    public void clear() {
+        synchronized (invocations) {
+            invocations.clear();
+        }
+    }
+
     public boolean isEmpty() {
         synchronized (invocations) {
             return invocations.isEmpty();
@@ -52,7 +60,7 @@
 
     private static class RemoveToString implements Filter<Invocation> {
         public boolean isOut(Invocation invocation) {
-            return new ObjectMethodsGuru().isToString(invocation.getMethod());
+            return isToStringMethod(invocation.getMethod());
         }
     }
 
diff --git a/src/main/java/org/mockito/internal/verification/Description.java b/src/main/java/org/mockito/internal/verification/Description.java
new file mode 100644
index 0000000..b11f99a
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/Description.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationMode;
+
+/**
+ * Description verification mode wraps an existing verification mode and prepends
+ * a custom message to the assertion error if verification fails.
+ * @author Geoff.Schoeman
+ * @since 2.1.0
+ */
+public class Description implements VerificationMode {
+
+    private final VerificationMode verification;
+    private final String description;
+
+    /**
+     * Constructs a verification mode which wraps the given verification mode.
+     * @param verification The implementation to use for verification
+     * @param description The failure message to prepend if verification fails
+     */
+    public Description(VerificationMode verification, String description) {
+        this.verification = verification;
+        this.description = description;
+    }
+
+    /**
+     * Performs verification using the wrapped verification mode implementation.
+     * Prepends the custom failure message if verification fails.
+     * @param data the data to be verified
+     */
+    @Override
+    public void verify(VerificationData data) {
+        try {
+            verification.verify(data);
+
+        } catch (MockitoAssertionError e) {
+            throw new MockitoAssertionError(e, description);
+        }
+    }
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/InOrderContextImpl.java b/src/main/java/org/mockito/internal/verification/InOrderContextImpl.java
index 5058d75..b7a7a96 100644
--- a/src/main/java/org/mockito/internal/verification/InOrderContextImpl.java
+++ b/src/main/java/org/mockito/internal/verification/InOrderContextImpl.java
@@ -2,21 +2,21 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification;

-

-import org.mockito.internal.util.collections.IdentitySet;

-import org.mockito.internal.verification.api.InOrderContext;

-import org.mockito.invocation.Invocation;

-

-public class InOrderContextImpl implements InOrderContext {

-    

-    final IdentitySet verified = new IdentitySet();

-

-    public boolean isVerified(Invocation invocation) {

-        return verified.contains(invocation);

-    }

-

-    public void markVerified(Invocation i) {

-        verified.add(i);

-    }

-}
\ No newline at end of file
+package org.mockito.internal.verification;
+
+import org.mockito.internal.util.collections.IdentitySet;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+
+public class InOrderContextImpl implements InOrderContext {
+
+    final IdentitySet verified = new IdentitySet();
+
+    public boolean isVerified(Invocation invocation) {
+        return verified.contains(invocation);
+    }
+
+    public void markVerified(Invocation i) {
+        verified.add(i);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/InOrderWrapper.java b/src/main/java/org/mockito/internal/verification/InOrderWrapper.java
index 9ed1075..88a4d70 100644
--- a/src/main/java/org/mockito/internal/verification/InOrderWrapper.java
+++ b/src/main/java/org/mockito/internal/verification/InOrderWrapper.java
@@ -2,31 +2,36 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification;

-

-import org.mockito.internal.InOrderImpl;

-import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;

-import org.mockito.internal.verification.api.VerificationData;

-import org.mockito.internal.verification.api.VerificationDataInOrderImpl;

-import org.mockito.internal.verification.api.VerificationInOrderMode;

-import org.mockito.invocation.Invocation;

-import org.mockito.verification.VerificationMode;

-

-import java.util.List;

-

-public class InOrderWrapper implements VerificationMode {

-

-    private final VerificationInOrderMode mode;

-    private final InOrderImpl inOrder;

-

-    public InOrderWrapper(VerificationInOrderMode mode, InOrderImpl inOrder) {

-        this.mode = mode;

-        this.inOrder = inOrder;        

-    }

-

-    public void verify(VerificationData data) {

-        List<Invocation> invocations = new VerifiableInvocationsFinder().find(inOrder.getMocksToBeVerifiedInOrder());

-        VerificationDataInOrderImpl dataInOrder = new VerificationDataInOrderImpl(inOrder, invocations, data.getWanted());

-        mode.verifyInOrder(dataInOrder);

-    }

-}
\ No newline at end of file
+package org.mockito.internal.verification;
+
+import org.mockito.internal.InOrderImpl;
+import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationDataInOrderImpl;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+import java.util.List;
+
+public class InOrderWrapper implements VerificationMode {
+
+    private final VerificationInOrderMode mode;
+    private final InOrderImpl inOrder;
+
+    public InOrderWrapper(VerificationInOrderMode mode, InOrderImpl inOrder) {
+        this.mode = mode;
+        this.inOrder = inOrder;
+    }
+
+    public void verify(VerificationData data) {
+        List<Invocation> invocations = VerifiableInvocationsFinder.find(inOrder.getMocksToBeVerifiedInOrder());
+        VerificationDataInOrderImpl dataInOrder = new VerificationDataInOrderImpl(inOrder, invocations, data.getTarget());
+        mode.verifyInOrder(dataInOrder);
+    }
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/MockAwareVerificationMode.java b/src/main/java/org/mockito/internal/verification/MockAwareVerificationMode.java
index 9c4f155..af4c0e8 100644
--- a/src/main/java/org/mockito/internal/verification/MockAwareVerificationMode.java
+++ b/src/main/java/org/mockito/internal/verification/MockAwareVerificationMode.java
@@ -2,26 +2,51 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification;

-

-import org.mockito.internal.verification.api.VerificationData;

-import org.mockito.verification.VerificationMode;

-

-public class MockAwareVerificationMode implements VerificationMode {

-

-    private final Object mock;

-    private final VerificationMode mode;

-

-    public MockAwareVerificationMode(Object mock, VerificationMode mode) {

-        this.mock = mock;

-        this.mode = mode;

-    }

-

-    public void verify(VerificationData data) {

-        mode.verify(data);

-    }

-

-    public Object getMock() {

-        return mock;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.verification;
+
+import java.util.Set;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.listeners.VerificationListener;
+import org.mockito.verification.VerificationEvent;
+import org.mockito.verification.VerificationMode;
+
+public class MockAwareVerificationMode implements VerificationMode {
+
+    private final Object mock;
+    private final VerificationMode mode;
+    private final Set<VerificationListener> listeners;
+
+    public MockAwareVerificationMode(Object mock, VerificationMode mode, Set<VerificationListener> listeners) {
+        this.mock = mock;
+        this.mode = mode;
+        this.listeners = listeners;
+    }
+
+    public void verify(VerificationData data) {
+        try {
+            mode.verify(data);
+            notifyListeners(new VerificationEventImpl(mock, mode, data, null));
+        } catch (RuntimeException e) {
+            notifyListeners(new VerificationEventImpl(mock, mode, data, e));
+            throw e;
+        } catch (Error e) {
+            notifyListeners(new VerificationEventImpl(mock, mode, data, e));
+            throw e;
+        }
+    }
+
+
+    private void notifyListeners(VerificationEvent event) {
+        for (VerificationListener listener : listeners) {
+            listener.onVerification(event);
+        }
+    }
+
+    public Object getMock() {
+        return mock;
+    }
+
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java b/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java
index 9b7642f..8110849 100644
--- a/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java
+++ b/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java
@@ -5,10 +5,13 @@
 
 package org.mockito.internal.verification;
 
+import static org.mockito.internal.exceptions.Reporter.noMoreInteractionsWanted;
+import static org.mockito.internal.exceptions.Reporter.noMoreInteractionsWantedInOrder;
+import static org.mockito.internal.invocation.InvocationsFinder.findFirstUnverified;
+import static org.mockito.internal.invocation.InvocationsFinder.findFirstUnverifiedInOrder;
+
 import java.util.List;
 
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationsFinder;
 import org.mockito.internal.verification.api.VerificationData;
 import org.mockito.internal.verification.api.VerificationDataInOrder;
 import org.mockito.internal.verification.api.VerificationInOrderMode;
@@ -19,18 +22,23 @@
 
     @SuppressWarnings("unchecked")
     public void verify(VerificationData data) {
-        Invocation unverified = new InvocationsFinder().findFirstUnverified(data.getAllInvocations());
+        Invocation unverified = findFirstUnverified(data.getAllInvocations());
         if (unverified != null) {
-            new Reporter().noMoreInteractionsWanted(unverified, (List) data.getAllInvocations());
+            throw noMoreInteractionsWanted(unverified, (List) data.getAllInvocations());
         }
     }
 
     public void verifyInOrder(VerificationDataInOrder data) {
         List<Invocation> invocations = data.getAllInvocations();
-        Invocation unverified = new InvocationsFinder().findFirstUnverifiedInOrder(data.getOrderingContext(), invocations);
-        
+        Invocation unverified = findFirstUnverifiedInOrder(data.getOrderingContext(), invocations);
+
         if (unverified != null) {
-            new Reporter().noMoreInteractionsWantedInOrder(unverified);
+            throw noMoreInteractionsWantedInOrder(unverified);
         }
     }
-}
\ No newline at end of file
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/Only.java b/src/main/java/org/mockito/internal/verification/Only.java
index 70f1fda..186c469 100644
--- a/src/main/java/org/mockito/internal/verification/Only.java
+++ b/src/main/java/org/mockito/internal/verification/Only.java
@@ -2,35 +2,40 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification;

-

-import java.util.List;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.invocation.InvocationMarker;

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.internal.invocation.InvocationsFinder;

-import org.mockito.internal.verification.api.VerificationData;

-import org.mockito.invocation.Invocation;

-import org.mockito.verification.VerificationMode;

-

-public class Only implements VerificationMode {

-

-	private final InvocationsFinder finder = new InvocationsFinder();

-	private final InvocationMarker marker = new InvocationMarker();

-	private final Reporter reporter = new Reporter();

-

-	@SuppressWarnings("unchecked")

-    public void verify(VerificationData data) {

-		InvocationMatcher wantedMatcher = data.getWanted();

-		List<Invocation> invocations = data.getAllInvocations();

-		List<Invocation> chunk = finder.findInvocations(invocations,wantedMatcher);

-		if (invocations.size() != 1 && chunk.size() > 0) {			

-			Invocation unverified = finder.findFirstUnverified(invocations);

-			reporter.noMoreInteractionsWanted(unverified, (List) invocations);

-		} else if (invocations.size() != 1 || chunk.size() == 0) {

-			reporter.wantedButNotInvoked(wantedMatcher);

-		}

-		marker.markVerified(chunk.get(0), wantedMatcher);

-	}

-}

+package org.mockito.internal.verification;
+
+import static org.mockito.internal.exceptions.Reporter.noMoreInteractionsWanted;
+import static org.mockito.internal.exceptions.Reporter.wantedButNotInvoked;
+import static org.mockito.internal.invocation.InvocationMarker.markVerified;
+import static org.mockito.internal.invocation.InvocationsFinder.findFirstUnverified;
+import static org.mockito.internal.invocation.InvocationsFinder.findInvocations;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.MatchableInvocation;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class Only implements VerificationMode {
+
+    @SuppressWarnings("unchecked")
+    public void verify(VerificationData data) {
+        MatchableInvocation target = data.getTarget();
+        List<Invocation> invocations = data.getAllInvocations();
+        List<Invocation> chunk = findInvocations(invocations,target);
+        if (invocations.size() != 1 && chunk.size() > 0) {
+            Invocation unverified = findFirstUnverified(invocations);
+            throw noMoreInteractionsWanted(unverified, (List) invocations);
+        }
+        if (invocations.size() != 1 || chunk.size() == 0) {
+            throw wantedButNotInvoked(target);
+        }
+        markVerified(chunk.get(0), target);
+    }
+
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/RegisteredInvocations.java b/src/main/java/org/mockito/internal/verification/RegisteredInvocations.java
index 1cb2131..dcc49d9 100644
--- a/src/main/java/org/mockito/internal/verification/RegisteredInvocations.java
+++ b/src/main/java/org/mockito/internal/verification/RegisteredInvocations.java
@@ -5,9 +5,6 @@
 
 package org.mockito.internal.verification;
 
-import org.mockito.internal.util.ObjectMethodsGuru;
-import org.mockito.internal.util.collections.ListUtil;
-import org.mockito.internal.util.collections.ListUtil.Filter;
 import org.mockito.invocation.Invocation;
 
 import java.util.List;
@@ -21,6 +18,8 @@
 
     List<Invocation> getAll();
 
+    void clear();
+
     boolean isEmpty();
 
 }
diff --git a/src/main/java/org/mockito/internal/verification/SingleRegisteredInvocation.java b/src/main/java/org/mockito/internal/verification/SingleRegisteredInvocation.java
index 07da74c..67ceafa 100644
--- a/src/main/java/org/mockito/internal/verification/SingleRegisteredInvocation.java
+++ b/src/main/java/org/mockito/internal/verification/SingleRegisteredInvocation.java
@@ -27,6 +27,10 @@
         return Collections.emptyList();
     }
 
+    public void clear() {
+        invocation = null;
+    }
+
     public boolean isEmpty() {
         return invocation == null;
     }
diff --git a/src/main/java/org/mockito/internal/verification/Times.java b/src/main/java/org/mockito/internal/verification/Times.java
index 539ddf6..e786a23 100644
--- a/src/main/java/org/mockito/internal/verification/Times.java
+++ b/src/main/java/org/mockito/internal/verification/Times.java
@@ -5,54 +5,57 @@
 
 package org.mockito.internal.verification;
 
-import java.util.List;
+import static org.mockito.internal.verification.checkers.MissingInvocationChecker.checkMissingInvocation;
+import static org.mockito.internal.verification.checkers.NumberOfInvocationsChecker.checkNumberOfInvocations;
 
+import java.util.List;
 import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.MatchableInvocation;
 import org.mockito.internal.verification.api.VerificationData;
 import org.mockito.internal.verification.api.VerificationDataInOrder;
 import org.mockito.internal.verification.api.VerificationInOrderMode;
-import org.mockito.internal.verification.checkers.MissingInvocationChecker;
-import org.mockito.internal.verification.checkers.MissingInvocationInOrderChecker;
-import org.mockito.internal.verification.checkers.NumberOfInvocationsChecker;
-import org.mockito.internal.verification.checkers.NumberOfInvocationsInOrderChecker;
 import org.mockito.invocation.Invocation;
 import org.mockito.verification.VerificationMode;
 
 public class Times implements VerificationInOrderMode, VerificationMode {
-    
+
     final int wantedCount;
-    
+
     public Times(int wantedNumberOfInvocations) {
         if (wantedNumberOfInvocations < 0) {
             throw new MockitoException("Negative value is not allowed here");
         }
         this.wantedCount = wantedNumberOfInvocations;
     }
-    
+
+    @Override
     public void verify(VerificationData data) {
+        List<Invocation> invocations = data.getAllInvocations();
+        MatchableInvocation wanted = data.getTarget();
+
         if (wantedCount > 0) {
-            MissingInvocationChecker missingInvocation = new MissingInvocationChecker();
-            missingInvocation.check(data.getAllInvocations(), data.getWanted());
+             checkMissingInvocation(data.getAllInvocations(), data.getTarget());
         }
-        NumberOfInvocationsChecker numberOfInvocations = new NumberOfInvocationsChecker();
-        numberOfInvocations.check(data.getAllInvocations(), data.getWanted(), wantedCount);
+        checkNumberOfInvocations(invocations, wanted, wantedCount);
     }
-    
+    @Override
     public void verifyInOrder(VerificationDataInOrder data) {
         List<Invocation> allInvocations = data.getAllInvocations();
-        InvocationMatcher wanted = data.getWanted();
-        
+        MatchableInvocation wanted = data.getWanted();
+
         if (wantedCount > 0) {
-            MissingInvocationInOrderChecker missingInvocation = new MissingInvocationInOrderChecker();
-            missingInvocation.check(allInvocations, wanted, this, data.getOrderingContext());
+            checkMissingInvocation(allInvocations, wanted, data.getOrderingContext());
         }
-        NumberOfInvocationsInOrderChecker numberOfCalls = new NumberOfInvocationsInOrderChecker();
-        numberOfCalls.check(allInvocations, wanted, wantedCount, data.getOrderingContext());
-    }    
-    
+        checkNumberOfInvocations(allInvocations, wanted, wantedCount, data.getOrderingContext());
+    }
+
     @Override
     public String toString() {
         return "Wanted invocations count: " + wantedCount;
     }
-}
\ No newline at end of file
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/VerificationDataImpl.java b/src/main/java/org/mockito/internal/verification/VerificationDataImpl.java
index 870820b..a50221e 100644
--- a/src/main/java/org/mockito/internal/verification/VerificationDataImpl.java
+++ b/src/main/java/org/mockito/internal/verification/VerificationDataImpl.java
@@ -1,44 +1,52 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.internal.verification;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.internal.stubbing.InvocationContainer;

-import org.mockito.internal.util.ObjectMethodsGuru;

-import org.mockito.internal.verification.api.VerificationData;

-import org.mockito.invocation.Invocation;

-

-import java.util.List;

-

-public class VerificationDataImpl implements VerificationData {

-

-    private final InvocationMatcher wanted;

-    private final InvocationContainer invocations;

-

-    public VerificationDataImpl(InvocationContainer invocations, InvocationMatcher wanted) {

-        this.invocations = invocations;

-        this.wanted = wanted;

-        this.assertWantedIsVerifiable();

-    }

-

-    public List<Invocation> getAllInvocations() {

-        return invocations.getInvocations();

-    }

-

-    public InvocationMatcher getWanted() {

-        return wanted;

-    }

-

-    private void assertWantedIsVerifiable() {

-        if (wanted == null) {

-            return;

-        }

-        ObjectMethodsGuru o =  new ObjectMethodsGuru();

-        if (o.isToString(wanted.getMethod())) {

-            new Reporter().cannotVerifyToString();

-        }

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.invocation.MatchableInvocation;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+
+import static org.mockito.internal.exceptions.Reporter.cannotVerifyToString;
+import static org.mockito.internal.util.ObjectMethodsGuru.isToStringMethod;
+
+import java.util.List;
+
+public class VerificationDataImpl implements VerificationData {
+
+    private final InvocationMatcher wanted;
+    private final InvocationContainer invocations;
+
+    public VerificationDataImpl(InvocationContainer invocations, InvocationMatcher wanted) {
+        this.invocations = invocations;
+        this.wanted = wanted;
+        this.assertWantedIsVerifiable();
+    }
+
+    @Override
+    public List<Invocation> getAllInvocations() {
+        return invocations.getInvocations();
+    }
+
+    @Override
+    public MatchableInvocation getTarget() {
+        return wanted;
+    }
+
+    @Override
+    public InvocationMatcher getWanted() {
+        return wanted;
+    }
+
+    private void assertWantedIsVerifiable() {
+        if (wanted == null) {
+            return;
+        }
+        if (isToStringMethod(wanted.getMethod())) {
+            throw cannotVerifyToString();
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/VerificationEventImpl.java b/src/main/java/org/mockito/internal/verification/VerificationEventImpl.java
new file mode 100644
index 0000000..e9f10b7
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/VerificationEventImpl.java
@@ -0,0 +1,36 @@
+package org.mockito.internal.verification;
+
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationEvent;
+import org.mockito.verification.VerificationMode;
+
+public class VerificationEventImpl implements VerificationEvent {
+    private final Object mock;
+    private final VerificationMode mode;
+    private final VerificationData data;
+    private final Throwable cause;
+
+
+    public VerificationEventImpl(Object mock, VerificationMode mode, VerificationData data, Throwable cause) {
+        this.mock = mock;
+        this.mode = mode;
+        this.data = data;
+        this.cause = cause;
+    }
+
+    public Object getMock() {
+        return mock;
+    }
+
+    public VerificationMode getMode() {
+        return mode;
+    }
+
+    public VerificationData getData() {
+        return data;
+    }
+
+    public Throwable getVerificationError() {
+        return cause;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java b/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java
index 1657831..1f8e8b6 100644
--- a/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java
+++ b/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java
@@ -8,7 +8,7 @@
 import org.mockito.verification.VerificationMode;
 
 public class VerificationModeFactory {
-    
+
     public static VerificationMode atLeastOnce() {
         return atLeast(1);
     }
@@ -36,4 +36,15 @@
     public static VerificationMode atMost(int maxNumberOfInvocations) {
         return new AtMost(maxNumberOfInvocations);
     }
-}
\ No newline at end of file
+
+    /**
+     * Verification mode will prepend the specified failure message if verification fails with the given implementation.
+     * @param mode Implementation used for verification
+     * @param description The custom failure message
+     * @return VerificationMode
+     * @since 2.1.0
+     */
+    public static VerificationMode description(VerificationMode mode, String description) {
+        return new Description(mode, description);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java b/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java
index 5c67348..aa91dab 100644
--- a/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java
+++ b/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java
@@ -5,7 +5,6 @@
 package org.mockito.internal.verification;
 
 import org.mockito.exceptions.base.MockitoAssertionError;
-import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
 import org.mockito.internal.util.Timer;
 import org.mockito.internal.verification.api.VerificationData;
 import org.mockito.verification.VerificationMode;
@@ -18,11 +17,10 @@
 public class VerificationOverTimeImpl implements VerificationMode {
 
     private final long pollingPeriodMillis;
-    private final long durationMillis;
     private final VerificationMode delegate;
     private final boolean returnOnSuccess;
     private final Timer timer;
-    
+
     /**
      * Create this verification mode, to be used to verify invocation ongoing data later.
      *
@@ -35,18 +33,13 @@
      *                        {@link org.mockito.verification.VerificationAfterDelay}).
      */
     public VerificationOverTimeImpl(long pollingPeriodMillis, long durationMillis, VerificationMode delegate, boolean returnOnSuccess) {
-        this.pollingPeriodMillis = pollingPeriodMillis;
-        this.durationMillis = durationMillis;
-        this.delegate = delegate;
-        this.returnOnSuccess = returnOnSuccess;
-        this.timer = new Timer(durationMillis);
+        this(pollingPeriodMillis, delegate, returnOnSuccess, new Timer(durationMillis));
     }
 
     /**
      * Create this verification mode, to be used to verify invocation ongoing data later.
      *
      * @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied
-     * @param durationMillis The max time to wait (in millis) for the delegate verification mode to be satisfied
      * @param delegate The verification mode to delegate overall success or failure to
      * @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in
      *                        {@link org.mockito.verification.VerificationWithTimeout}, or to only return once
@@ -54,9 +47,8 @@
      *                        {@link org.mockito.verification.VerificationAfterDelay}).
      * @param timer Checker of whether the duration of the verification is still acceptable
      */
-    public VerificationOverTimeImpl(long pollingPeriodMillis, long durationMillis, VerificationMode delegate, boolean returnOnSuccess, Timer timer) {
+    public VerificationOverTimeImpl(long pollingPeriodMillis, VerificationMode delegate, boolean returnOnSuccess, Timer timer) {
         this.pollingPeriodMillis = pollingPeriodMillis;
-        this.durationMillis = durationMillis;
         this.delegate = delegate;
         this.returnOnSuccess = returnOnSuccess;
         this.timer = timer;
@@ -79,12 +71,12 @@
      */
     public void verify(VerificationData data) {
         AssertionError error = null;
-        
+
         timer.start();
         while (timer.isCounting()) {
             try {
                 delegate.verify(data);
-                
+
                 if (returnOnSuccess) {
                     return;
                 } else {
@@ -93,11 +85,11 @@
             } catch (MockitoAssertionError e) {
                 error = handleVerifyException(e);
             }
-            catch (ArgumentsAreDifferent e) {
+            catch (AssertionError e) {
                 error = handleVerifyException(e);
             }
         }
-        
+
         if (error != null) {
             throw error;
         }
@@ -116,24 +108,36 @@
         return !(verificationMode instanceof AtMost || verificationMode instanceof NoMoreInteractions);
     }
 
+    public VerificationOverTimeImpl copyWithVerificationMode(VerificationMode verificationMode) {
+        return new VerificationOverTimeImpl(pollingPeriodMillis, timer.duration(), verificationMode, returnOnSuccess);
+    }
+
     private void sleep(long sleep) {
         try {
             Thread.sleep(sleep);
         } catch (InterruptedException ie) {
-            // oups. not much luck.
+            throw new RuntimeException("Thread sleep has been interrupted", ie);
         }
     }
-    
-    public long getPollingPeriod() {
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+
+    public boolean isReturnOnSuccess() {
+        return returnOnSuccess;
+    }
+
+    public long getPollingPeriodMillis() {
         return pollingPeriodMillis;
     }
-    
-    public long getDuration() {
-        return durationMillis;
+
+    public Timer getTimer() {
+        return timer;
     }
-    
+
     public VerificationMode getDelegate() {
         return delegate;
     }
-    
 }
diff --git a/src/main/java/org/mockito/internal/verification/VerificationWrapper.java b/src/main/java/org/mockito/internal/verification/VerificationWrapper.java
new file mode 100644
index 0000000..b471342
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/VerificationWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationMode;
+
+public abstract class VerificationWrapper<WrapperType extends VerificationMode> implements VerificationMode {
+
+    protected final WrapperType wrappedVerification;
+
+    public VerificationWrapper(WrapperType wrappedVerification) {
+        this.wrappedVerification = wrappedVerification;
+    }
+
+    public void verify(VerificationData data) {
+        wrappedVerification.verify(data);
+    }
+
+    protected abstract VerificationMode copySelfWithNewVerificationMode(VerificationMode verificationMode);
+
+    public VerificationMode times(int wantedNumberOfInvocations) {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.times(wantedNumberOfInvocations));
+    }
+
+    public VerificationMode never() {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.atMost(0));
+    }
+
+    public VerificationMode atLeastOnce() {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.atLeastOnce());
+    }
+
+    public VerificationMode atLeast(int minNumberOfInvocations) {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.atLeast(minNumberOfInvocations));
+    }
+
+    public VerificationMode atMost(int maxNumberOfInvocations) {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.atMost(maxNumberOfInvocations));
+    }
+
+    public VerificationMode only() {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.only());
+    }
+
+}
diff --git a/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java b/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java
new file mode 100644
index 0000000..eded985
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.InOrderImpl;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.verification.VerificationMode;
+
+public class VerificationWrapperInOrderWrapper implements VerificationMode {
+    private final VerificationMode delegate;
+
+    public VerificationWrapperInOrderWrapper(VerificationWrapper<?> verificationWrapper, InOrderImpl inOrder) {
+        VerificationMode verificationMode = verificationWrapper.wrappedVerification;
+
+        VerificationMode inOrderWrappedVerificationMode = wrapInOrder(verificationWrapper, verificationMode, inOrder);
+
+        delegate = verificationWrapper.copySelfWithNewVerificationMode(inOrderWrappedVerificationMode);
+    }
+
+    @Override
+    public void verify(VerificationData data) {
+        delegate.verify(data);
+    }
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+
+    private VerificationMode wrapInOrder(VerificationWrapper<?> verificationWrapper, VerificationMode verificationMode, InOrderImpl inOrder) {
+        if (verificationMode instanceof VerificationInOrderMode) {
+            final VerificationInOrderMode verificationInOrderMode = (VerificationInOrderMode)verificationMode;
+            return new InOrderWrapper(verificationInOrderMode, inOrder);
+        }
+
+        if (verificationMode instanceof VerificationOverTimeImpl) {
+            final VerificationOverTimeImpl verificationOverTime = (VerificationOverTimeImpl)verificationMode;
+            if (verificationOverTime.isReturnOnSuccess()) {
+                return new VerificationOverTimeImpl(verificationOverTime.getPollingPeriodMillis(),
+                        verificationOverTime.getTimer().duration(),
+                        wrapInOrder(verificationWrapper, verificationOverTime.getDelegate(), inOrder),
+                        verificationOverTime.isReturnOnSuccess());
+            }
+        }
+
+        throw new MockitoException(verificationMode.getClass().getSimpleName() +
+                " is not implemented to work with InOrder wrapped inside a " +
+                verificationWrapper.getClass().getSimpleName());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/api/InOrderContext.java b/src/main/java/org/mockito/internal/verification/api/InOrderContext.java
index 5186f42..c6953be 100644
--- a/src/main/java/org/mockito/internal/verification/api/InOrderContext.java
+++ b/src/main/java/org/mockito/internal/verification/api/InOrderContext.java
@@ -2,14 +2,14 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.api;

-

-import org.mockito.invocation.Invocation;

-

-public interface InOrderContext {

-

-    boolean isVerified(Invocation invocation);

-

-    void markVerified(Invocation i);

-

-}

+package org.mockito.internal.verification.api;
+
+import org.mockito.invocation.Invocation;
+
+public interface InOrderContext {
+
+    boolean isVerified(Invocation invocation);
+
+    void markVerified(Invocation i);
+
+}
diff --git a/src/main/java/org/mockito/internal/verification/api/VerificationData.java b/src/main/java/org/mockito/internal/verification/api/VerificationData.java
index 4ed17ae..fd102ed 100644
--- a/src/main/java/org/mockito/internal/verification/api/VerificationData.java
+++ b/src/main/java/org/mockito/internal/verification/api/VerificationData.java
@@ -2,17 +2,50 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.api;

-

-import java.util.List;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.Invocation;

-

-public interface VerificationData {

-

-    List<Invocation> getAllInvocations();

-

-    InvocationMatcher getWanted();   

-    

-}
\ No newline at end of file
+package org.mockito.internal.verification.api;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+import java.util.List;
+
+/**
+ * Data needed to perform verification of interactions.
+ * This interface is considered public even though it lives in private package.
+ * In the next major version of Mockito, this class will be moved to public space.
+ */
+public interface VerificationData {
+
+    /**
+     * All invocations recorded on the mock object that is being verified.
+     * Does not include invocations recorded on other mock objects.
+     */
+    List<Invocation> getAllInvocations();
+
+    /**
+     * The target or wanted invocation.
+     * Below example illustrates what is the 'target' invocation:
+     * <pre class="code"><code class="java">
+     *   mock.foo();   // <- invocation 1
+     *   mock.bar();   // <- invocation 2
+     *
+     *   verify(mock).bar();  // <- target invocation
+     * </code></pre>
+     *
+     * Target invocation can contain argument matchers therefore the returned type is {@link MatchableInvocation}
+     * and not {@link Invocation}.
+     *
+     * @since 2.2.12
+     */
+    MatchableInvocation getTarget();
+
+    /**
+     * @deprecated - This internal method leaks internal class <code>InvocationMatcher</code>.
+     * Please use {@link org.mockito.internal.verification.api.VerificationData#getTarget()} instead.
+     *
+     * Deprecated since 2.2.12
+     */
+    @Deprecated
+    InvocationMatcher getWanted();
+}
diff --git a/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrder.java b/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrder.java
index 1abb122..cf2ade2 100644
--- a/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrder.java
+++ b/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrder.java
@@ -2,19 +2,20 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.api;

-

-import java.util.List;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.Invocation;

-

-public interface VerificationDataInOrder {

-

-    List<Invocation> getAllInvocations();

-

-    InvocationMatcher getWanted();   

-    

-    InOrderContext getOrderingContext(); 

-    

-}
\ No newline at end of file
+package org.mockito.internal.verification.api;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+public interface VerificationDataInOrder {
+
+    List<Invocation> getAllInvocations();
+
+    MatchableInvocation getWanted();
+
+    InOrderContext getOrderingContext();
+
+}
diff --git a/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java b/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java
index 7cb158b..3f318af 100644
--- a/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java
+++ b/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java
@@ -2,34 +2,35 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.api;

-

-import java.util.List;

-

-import org.mockito.internal.invocation.InvocationMatcher;

-import org.mockito.invocation.Invocation;

-

-public class VerificationDataInOrderImpl implements VerificationDataInOrder {

-

-    private final InOrderContext inOrder;

-    private final List<Invocation> allInvocations;

-    private final InvocationMatcher wanted;

-

-    public VerificationDataInOrderImpl(InOrderContext inOrder, List<Invocation> allInvocations, InvocationMatcher wanted) {

-        this.inOrder = inOrder;

-        this.allInvocations = allInvocations;

-        this.wanted = wanted;        

-    }

-

-    public List<Invocation> getAllInvocations() {

-        return allInvocations;

-    }

-

-    public InOrderContext getOrderingContext() {

-        return inOrder;

-    }

-

-    public InvocationMatcher getWanted() {

-        return wanted;

-    }

-}
\ No newline at end of file
+package org.mockito.internal.verification.api;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+
+public class VerificationDataInOrderImpl implements VerificationDataInOrder {
+
+    private final InOrderContext inOrder;
+    private final List<Invocation> allInvocations;
+    private final MatchableInvocation wanted;
+
+    public VerificationDataInOrderImpl(InOrderContext inOrder, List<Invocation> allInvocations, MatchableInvocation wanted) {
+        this.inOrder = inOrder;
+        this.allInvocations = allInvocations;
+        this.wanted = wanted;
+    }
+
+    public List<Invocation> getAllInvocations() {
+        return allInvocations;
+    }
+
+    public InOrderContext getOrderingContext() {
+        return inOrder;
+    }
+
+    public MatchableInvocation getWanted() {
+        return wanted;
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/api/VerificationInOrderMode.java b/src/main/java/org/mockito/internal/verification/api/VerificationInOrderMode.java
index 97df3f0..6c2d110 100644
--- a/src/main/java/org/mockito/internal/verification/api/VerificationInOrderMode.java
+++ b/src/main/java/org/mockito/internal/verification/api/VerificationInOrderMode.java
@@ -2,9 +2,9 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.api;

-

-public interface VerificationInOrderMode {

-    

-    void verifyInOrder(VerificationDataInOrder data);    

-}
\ No newline at end of file
+package org.mockito.internal.verification.api;
+
+public interface VerificationInOrderMode {
+
+    void verifyInOrder(VerificationDataInOrder data);
+}
diff --git a/src/main/java/org/mockito/internal/verification/api/package-info.java b/src/main/java/org/mockito/internal/verification/api/package-info.java
new file mode 100644
index 0000000..321fd93
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/api/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * This package should be open to public once verification API is fully finished.
+ */
+package org.mockito.internal.verification.api;
diff --git a/src/main/java/org/mockito/internal/verification/api/package.html b/src/main/java/org/mockito/internal/verification/api/package.html
deleted file mode 100644
index 0001538..0000000
--- a/src/main/java/org/mockito/internal/verification/api/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-This package should be open to public once verification API is fully finished
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java b/src/main/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java
index 8f983e3..af31d60 100644
--- a/src/main/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java
+++ b/src/main/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java
@@ -2,49 +2,49 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.argumentmatching;

-

-import java.util.LinkedList;

-import java.util.List;

-

-import org.hamcrest.Matcher;

-import org.hamcrest.StringDescription;

-import org.mockito.internal.matchers.ContainsExtraTypeInformation;

-

-@SuppressWarnings("unchecked")

-public class ArgumentMatchingTool {

-

-    /**

-     * Suspiciously not matching arguments are those that don't match, the toString() representation is the same but types are different.

-     */

-    public Integer[] getSuspiciouslyNotMatchingArgsIndexes(List<Matcher> matchers, Object[] arguments) {

-        if (matchers.size() != arguments.length) {

-            return new Integer[0];

-        }

-        

-        List<Integer> suspicious = new LinkedList<Integer>();

-        int i = 0;

-        for (Matcher m : matchers) {

-            if (m instanceof ContainsExtraTypeInformation 

-                    && !safelyMatches(m, arguments[i]) 

-                    && toStringEquals(m, arguments[i])

-                    && !((ContainsExtraTypeInformation) m).typeMatches(arguments[i])) {

-                suspicious.add(i);

-            }

-            i++;

-        }

-        return suspicious.toArray(new Integer[0]);

-    }

-

-    private boolean safelyMatches(Matcher m, Object arg) {

-        try {

-            return m.matches(arg);

-        } catch (Throwable t) {

-            return false;

-        }

-    }

-

-    private boolean toStringEquals(Matcher m, Object arg) {

-        return StringDescription.toString(m).equals(arg == null? "null" : arg.toString());

-    }

-}

+package org.mockito.internal.verification.argumentmatching;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.ContainsExtraTypeInfo;
+
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class ArgumentMatchingTool {
+
+    private ArgumentMatchingTool(){}
+    /**
+     * Suspiciously not matching arguments are those that don't match, the toString() representation is the same but types are different.
+     */
+    public static Integer[] getSuspiciouslyNotMatchingArgsIndexes(List<ArgumentMatcher> matchers, Object[] arguments) {
+        if (matchers.size() != arguments.length) {
+            return new Integer[0];
+        }
+
+        List<Integer> suspicious = new LinkedList<Integer>();
+        int i = 0;
+        for (ArgumentMatcher m : matchers) {
+            if (m instanceof ContainsExtraTypeInfo
+                    && !safelyMatches(m, arguments[i])
+                    && toStringEquals(m, arguments[i])
+                    && !((ContainsExtraTypeInfo) m).typeMatches(arguments[i])) {
+                suspicious.add(i);
+            }
+            i++;
+        }
+        return suspicious.toArray(new Integer[0]);
+    }
+
+    private static boolean safelyMatches(ArgumentMatcher m, Object arg) {
+        try {
+            return m.matches(arg);
+        } catch (Throwable t) {
+            return false;
+        }
+    }
+
+    private static boolean toStringEquals(ArgumentMatcher m, Object arg) {
+        return m.toString().equals(arg == null ? "null" : arg.toString());
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/argumentmatching/package-info.java b/src/main/java/org/mockito/internal/verification/argumentmatching/package-info.java
new file mode 100644
index 0000000..f65bd9c
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/argumentmatching/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Deals with matching arguments.
+ */
+package org.mockito.internal.verification.argumentmatching;
diff --git a/src/main/java/org/mockito/internal/verification/argumentmatching/package.html b/src/main/java/org/mockito/internal/verification/argumentmatching/package.html
deleted file mode 100644
index d71855e..0000000
--- a/src/main/java/org/mockito/internal/verification/argumentmatching/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Deals with matching arguments
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java b/src/main/java/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java
index 0f02e9c..be09141 100644
--- a/src/main/java/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java
+++ b/src/main/java/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java
@@ -2,18 +2,18 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.internal.verification.checkers;

-

-import org.mockito.internal.reporting.Discrepancy;

-

-public class AtLeastDiscrepancy extends Discrepancy {

-

-    public AtLeastDiscrepancy(int wantedCount, int actualCount) {

-        super(wantedCount, actualCount);

-    }

-    

-    @Override

-    public String getPluralizedWantedCount() {

-        return "*at least* " + super.getPluralizedWantedCount();

-    }

-}
\ No newline at end of file
+package org.mockito.internal.verification.checkers;
+
+import org.mockito.internal.reporting.Discrepancy;
+
+public class AtLeastDiscrepancy extends Discrepancy {
+
+    public AtLeastDiscrepancy(int wantedCount, int actualCount) {
+        super(wantedCount, actualCount);
+    }
+
+    @Override
+    public String getPluralizedWantedCount() {
+        return "*at least* " + super.getPluralizedWantedCount();
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java b/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java
index cc29e09..36e35a3 100644
--- a/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java
+++ b/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java
@@ -6,29 +6,43 @@
 package org.mockito.internal.verification.checkers;
 
 import java.util.List;
-
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationMarker;
-import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.InOrderContext;
 import org.mockito.invocation.Invocation;
 import org.mockito.invocation.Location;
+import org.mockito.invocation.MatchableInvocation;
+
+import static org.mockito.internal.exceptions.Reporter.tooLittleActualInvocations;
+import static org.mockito.internal.exceptions.Reporter.tooLittleActualInvocationsInOrder;
+import static org.mockito.internal.invocation.InvocationMarker.markVerified;
+import static org.mockito.internal.invocation.InvocationMarker.markVerifiedInOrder;
+import static org.mockito.internal.invocation.InvocationsFinder.findAllMatchingUnverifiedChunks;
+import static org.mockito.internal.invocation.InvocationsFinder.findInvocations;
+import static org.mockito.internal.invocation.InvocationsFinder.getLastLocation;
 
 public class AtLeastXNumberOfInvocationsChecker {
-    
-    Reporter reporter = new Reporter();
-    InvocationsFinder finder = new InvocationsFinder();
-    InvocationMarker invocationMarker = new InvocationMarker();
 
-    public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount) {
-        List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
-        
+    public static void checkAtLeastNumberOfInvocations(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount) {
+        List<Invocation> actualInvocations = findInvocations(invocations, wanted);
+
         int actualCount = actualInvocations.size();
         if (wantedCount > actualCount) {
-            Location lastLocation = finder.getLastLocation(actualInvocations);
-            reporter.tooLittleActualInvocations(new AtLeastDiscrepancy(wantedCount, actualCount), wanted, lastLocation);        
+            Location lastLocation = getLastLocation(actualInvocations);
+            throw tooLittleActualInvocations(new AtLeastDiscrepancy(wantedCount, actualCount), wanted, lastLocation);
         }
-        
-        invocationMarker.markVerified(actualInvocations, wanted);
+
+        markVerified(actualInvocations, wanted);
     }
-}
\ No newline at end of file
+
+    public static void checkAtLeastNumberOfInvocations(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount,InOrderContext orderingContext) {
+        List<Invocation> chunk = findAllMatchingUnverifiedChunks(invocations, wanted, orderingContext);
+
+        int actualCount = chunk.size();
+
+        if (wantedCount > actualCount) {
+            Location lastLocation = getLastLocation(chunk);
+            throw tooLittleActualInvocationsInOrder(new AtLeastDiscrepancy(wantedCount, actualCount), wanted, lastLocation);
+        }
+
+        markVerifiedInOrder(chunk, wanted, orderingContext);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsInOrderChecker.java b/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsInOrderChecker.java
deleted file mode 100644
index 5ed877e..0000000
--- a/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsInOrderChecker.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.verification.checkers;
-
-import java.util.List;
-
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationMarker;
-import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationsFinder;
-import org.mockito.internal.verification.api.InOrderContext;
-import org.mockito.invocation.Invocation;
-import org.mockito.invocation.Location;
-
-public class AtLeastXNumberOfInvocationsInOrderChecker {
-    
-    private final Reporter reporter = new Reporter();
-    private final InvocationsFinder finder = new InvocationsFinder();
-    private final InvocationMarker invocationMarker = new InvocationMarker();
-    private final InOrderContext orderingContext;
-    
-    public AtLeastXNumberOfInvocationsInOrderChecker(InOrderContext orderingContext) {
-        this.orderingContext = orderingContext;
-    }
-
-    public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount) {
-        List<Invocation> chunk = finder.findAllMatchingUnverifiedChunks(invocations, wanted, orderingContext);
-        
-        int actualCount = chunk.size();
-        
-        if (wantedCount > actualCount) {
-            Location lastLocation = finder.getLastLocation(chunk);
-            reporter.tooLittleActualInvocationsInOrder(new AtLeastDiscrepancy(wantedCount, actualCount), wanted, lastLocation);
-        }
-        
-        invocationMarker.markVerifiedInOrder(chunk, wanted, orderingContext);
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationChecker.java b/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationChecker.java
index 2fddf16..584f380 100644
--- a/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationChecker.java
+++ b/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationChecker.java
@@ -5,42 +5,57 @@
 
 package org.mockito.internal.verification.checkers;
 
-import java.util.List;
+import static org.mockito.internal.exceptions.Reporter.argumentsAreDifferent;
+import static org.mockito.internal.exceptions.Reporter.wantedButNotInvoked;
+import static org.mockito.internal.exceptions.Reporter.wantedButNotInvokedInOrder;
+import static org.mockito.internal.invocation.InvocationsFinder.findAllMatchingUnverifiedChunks;
+import static org.mockito.internal.invocation.InvocationsFinder.findInvocations;
+import static org.mockito.internal.invocation.InvocationsFinder.findPreviousVerifiedInOrder;
+import static org.mockito.internal.invocation.InvocationsFinder.findSimilarInvocation;
+import static org.mockito.internal.verification.argumentmatching.ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes;
 
-import org.mockito.exceptions.Reporter;
+import java.util.List;
 import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationsFinder;
 import org.mockito.internal.reporting.SmartPrinter;
-import org.mockito.internal.verification.argumentmatching.ArgumentMatchingTool;
+import org.mockito.internal.verification.api.InOrderContext;
 import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
 
 public class MissingInvocationChecker {
-    
-    private final Reporter reporter;
-    private final InvocationsFinder finder;
-    
-    public MissingInvocationChecker() {
-        this(new InvocationsFinder(), new Reporter());
+
+    private MissingInvocationChecker() {
     }
-    
-    MissingInvocationChecker(InvocationsFinder finder, Reporter reporter) {
-        this.finder = finder;
-        this.reporter = reporter;
-    }
-    
-    public void check(List<Invocation> invocations, InvocationMatcher wanted) {
-        List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
-        
-        if (actualInvocations.isEmpty()) {
-            Invocation similar = finder.findSimilarInvocation(invocations, wanted);
-            if (similar != null) {
-                ArgumentMatchingTool argumentMatchingTool = new ArgumentMatchingTool();
-                Integer[] indexesOfSuspiciousArgs = argumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes(wanted.getMatchers(), similar.getArguments());
-                SmartPrinter smartPrinter = new SmartPrinter(wanted, similar, indexesOfSuspiciousArgs);
-                reporter.argumentsAreDifferent(smartPrinter.getWanted(), smartPrinter.getActual(), similar.getLocation());
-            } else {
-                reporter.wantedButNotInvoked(wanted, invocations);
-            }
+
+    public static void checkMissingInvocation(List<Invocation> invocations, MatchableInvocation wanted) {
+        List<Invocation> actualInvocations = findInvocations(invocations, wanted);
+
+        if (!actualInvocations.isEmpty()){
+            return;
         }
+
+        Invocation similar = findSimilarInvocation(invocations, wanted);
+        if (similar == null) {
+            throw wantedButNotInvoked(wanted, invocations);
+        }
+
+        Integer[] indexesOfSuspiciousArgs = getSuspiciouslyNotMatchingArgsIndexes(wanted.getMatchers(), similar.getArguments());
+        SmartPrinter smartPrinter = new SmartPrinter(wanted, similar, indexesOfSuspiciousArgs);
+        throw argumentsAreDifferent(smartPrinter.getWanted(), smartPrinter.getActual(), similar.getLocation());
+
     }
-}
\ No newline at end of file
+
+    public static void checkMissingInvocation(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext context) {
+        List<Invocation> chunk = findAllMatchingUnverifiedChunks(invocations, wanted, context);
+
+        if (!chunk.isEmpty()) {
+            return;
+        }
+
+        Invocation previousInOrder = findPreviousVerifiedInOrder(invocations, context);
+        if (previousInOrder != null) {
+            throw wantedButNotInvokedInOrder(wanted, previousInOrder);
+        }
+
+        checkMissingInvocation(invocations, wanted);
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationInOrderChecker.java b/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationInOrderChecker.java
deleted file mode 100644
index 049c937..0000000
--- a/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationInOrderChecker.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.verification.checkers;
-
-import java.util.List;
-
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationsFinder;
-import org.mockito.internal.reporting.SmartPrinter;
-import org.mockito.internal.verification.api.InOrderContext;
-import org.mockito.internal.verification.argumentmatching.ArgumentMatchingTool;
-import org.mockito.invocation.Invocation;
-import org.mockito.verification.VerificationMode;
-
-public class MissingInvocationInOrderChecker {
-    
-    private final Reporter reporter;
-    private final InvocationsFinder finder;
-    
-    public MissingInvocationInOrderChecker() {
-        this(new InvocationsFinder(), new Reporter());
-    }
-    
-    MissingInvocationInOrderChecker(InvocationsFinder finder, Reporter reporter) {
-        this.finder = finder;
-        this.reporter = reporter;
-    }
-    
-    public void check(List<Invocation> invocations, InvocationMatcher wanted, VerificationMode mode, InOrderContext context) {
-        List<Invocation> chunk = finder.findAllMatchingUnverifiedChunks(invocations, wanted, context);
-        
-        if (!chunk.isEmpty()) {
-            return;
-        }
-        
-        Invocation previousInOrder = finder.findPreviousVerifiedInOrder(invocations, context);
-        if (previousInOrder == null) {
-            /**
-             * It is of course possible to have an issue where the arguments are different
-             * rather that not invoked in order. Issue related to
-             * http://code.google.com/p/mockito/issues/detail?id=27. If the previous order
-             * is missing, then this method checks if the arguments are different or if the order
-             * is not invoked.
-             */
-             List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
-             if (actualInvocations == null || actualInvocations.isEmpty())  {
-                 Invocation similar = finder.findSimilarInvocation(invocations, wanted);
-                 if (similar != null) {
-                     Integer[] indicesOfSimilarMatchingArguments =
-                             new ArgumentMatchingTool().getSuspiciouslyNotMatchingArgsIndexes(wanted.getMatchers(),
-                                     similar.getArguments());
-                     SmartPrinter smartPrinter = new SmartPrinter(wanted, similar, indicesOfSimilarMatchingArguments);
-                     reporter.argumentsAreDifferent(smartPrinter.getWanted(), smartPrinter.getActual(), similar.getLocation());
-                 } else {
-                     reporter.wantedButNotInvoked(wanted);
-                 }
-             }
-        } else {
-            reporter.wantedButNotInvokedInOrder(wanted, previousInOrder);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java b/src/main/java/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java
deleted file mode 100644
index e9d73d9..0000000
--- a/src/main/java/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.internal.verification.checkers;
-
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationMarker;
-import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationsFinder;
-import org.mockito.internal.reporting.Discrepancy;
-import org.mockito.internal.verification.api.InOrderContext;
-import org.mockito.invocation.Invocation;
-import org.mockito.invocation.Location;
-
-import java.util.List;
-
-public class NonGreedyNumberOfInvocationsInOrderChecker {
-
-    private final InvocationsFinder finder;
-    private final Reporter reporter;
-    private final InvocationMarker marker;
-
-    public NonGreedyNumberOfInvocationsInOrderChecker() {
-        this(new InvocationsFinder(), new Reporter(), new InvocationMarker());
-    }
-
-    NonGreedyNumberOfInvocationsInOrderChecker(InvocationsFinder finder, Reporter reporter, InvocationMarker marker ) {
-        this.finder = finder;
-        this.reporter = reporter;
-        this.marker = marker;
-    }
-    
-    public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount, InOrderContext context) {
-        int actualCount = 0;
-        Location lastLocation = null;
-        while( actualCount < wantedCount ){
-            Invocation next = finder.findFirstMatchingUnverifiedInvocation( invocations, wanted, context );
-            if( next == null ){
-                reporter.tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastLocation );
-            }
-            marker.markVerified( next, wanted );
-            context.markVerified( next );
-            lastLocation = next.getLocation();
-            actualCount++;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java b/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java
index 17dec9f..3fa340f 100644
--- a/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java
+++ b/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java
@@ -6,45 +6,78 @@
 package org.mockito.internal.verification.checkers;
 
 import java.util.List;
-
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationMarker;
-import org.mockito.internal.invocation.InvocationsFinder;
 import org.mockito.internal.reporting.Discrepancy;
+import org.mockito.internal.verification.api.InOrderContext;
 import org.mockito.invocation.Invocation;
 import org.mockito.invocation.Location;
+import org.mockito.invocation.MatchableInvocation;
+
+import static org.mockito.internal.exceptions.Reporter.neverWantedButInvoked;
+import static org.mockito.internal.exceptions.Reporter.tooLittleActualInvocations;
+import static org.mockito.internal.exceptions.Reporter.tooLittleActualInvocationsInOrder;
+import static org.mockito.internal.exceptions.Reporter.tooManyActualInvocations;
+import static org.mockito.internal.exceptions.Reporter.tooManyActualInvocationsInOrder;
+import static org.mockito.internal.invocation.InvocationMarker.markVerified;
+import static org.mockito.internal.invocation.InvocationMarker.markVerifiedInOrder;
+import static org.mockito.internal.invocation.InvocationsFinder.findFirstMatchingUnverifiedInvocation;
+import static org.mockito.internal.invocation.InvocationsFinder.findInvocations;
+import static org.mockito.internal.invocation.InvocationsFinder.findMatchingChunk;
+import static org.mockito.internal.invocation.InvocationsFinder.getLastLocation;
 
 public class NumberOfInvocationsChecker {
-    
-    private final Reporter reporter;
-    private final InvocationsFinder finder;
-    private final InvocationMarker invocationMarker = new InvocationMarker();
 
-    public NumberOfInvocationsChecker() {
-        this(new Reporter(), new InvocationsFinder());
+    private NumberOfInvocationsChecker() {
     }
-    
-    NumberOfInvocationsChecker(Reporter reporter, InvocationsFinder finder) {
-        this.reporter = reporter;
-        this.finder = finder;
-    }
-    
-    public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount) {
-        List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
-        
+
+    public static void checkNumberOfInvocations(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount) {
+        List<Invocation> actualInvocations = findInvocations(invocations, wanted);
+
         int actualCount = actualInvocations.size();
         if (wantedCount > actualCount) {
-            Location lastInvocation = finder.getLastLocation(actualInvocations);
-            reporter.tooLittleActualInvocations(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
-        } else if (wantedCount == 0 && actualCount > 0) {
-            Location firstUndesired = actualInvocations.get(wantedCount).getLocation();
-            reporter.neverWantedButInvoked(wanted, firstUndesired); 
-        } else if (wantedCount < actualCount) {
-            Location firstUndesired = actualInvocations.get(wantedCount).getLocation();
-            reporter.tooManyActualInvocations(wantedCount, actualCount, wanted, firstUndesired);
+            Location lastInvocation = getLastLocation(actualInvocations);
+            throw tooLittleActualInvocations(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
         }
-        
-        invocationMarker.markVerified(actualInvocations, wanted);
+        if (wantedCount == 0 && actualCount > 0) {
+            Location firstUndesired = actualInvocations.get(wantedCount).getLocation();
+            throw neverWantedButInvoked(wanted, firstUndesired);
+        }
+        if (wantedCount < actualCount) {
+            Location firstUndesired = actualInvocations.get(wantedCount).getLocation();
+            throw tooManyActualInvocations(wantedCount, actualCount, wanted, firstUndesired);
+        }
+
+        markVerified(actualInvocations, wanted);
     }
-}
\ No newline at end of file
+
+    public static void checkNumberOfInvocations(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount, InOrderContext context) {
+        List<Invocation> chunk = findMatchingChunk(invocations, wanted, wantedCount, context);
+
+        int actualCount = chunk.size();
+
+        if (wantedCount > actualCount) {
+            Location lastInvocation = getLastLocation(chunk);
+            throw tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
+        }
+        if (wantedCount < actualCount) {
+            Location firstUndesired = chunk.get(wantedCount).getLocation();
+            throw tooManyActualInvocationsInOrder(wantedCount, actualCount, wanted, firstUndesired);
+        }
+
+        markVerifiedInOrder(chunk, wanted, context);
+    }
+
+    public static void checkNumberOfInvocationsNonGreedy(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount, InOrderContext context) {
+        int actualCount = 0;
+        Location lastLocation = null;
+        while( actualCount < wantedCount ){
+            Invocation next = findFirstMatchingUnverifiedInvocation(invocations, wanted, context );
+            if( next == null ){
+                throw tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastLocation );
+            }
+            markVerified( next, wanted );
+            context.markVerified( next );
+            lastLocation = next.getLocation();
+            actualCount++;
+        }
+    }
+}
diff --git a/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java b/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java
index 98f9f23..e52d0b3 100644
--- a/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java
+++ b/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java
@@ -5,45 +5,37 @@
 
 package org.mockito.internal.verification.checkers;
 
+import static org.mockito.internal.exceptions.Reporter.tooLittleActualInvocationsInOrder;
+import static org.mockito.internal.exceptions.Reporter.tooManyActualInvocationsInOrder;
+import static org.mockito.internal.invocation.InvocationMarker.markVerifiedInOrder;
+import static org.mockito.internal.invocation.InvocationsFinder.findMatchingChunk;
+import static org.mockito.internal.invocation.InvocationsFinder.getLastLocation;
+
 import java.util.List;
 
-import org.mockito.exceptions.Reporter;
-import org.mockito.internal.invocation.InvocationMarker;
 import org.mockito.internal.invocation.InvocationMatcher;
-import org.mockito.internal.invocation.InvocationsFinder;
 import org.mockito.internal.reporting.Discrepancy;
 import org.mockito.internal.verification.api.InOrderContext;
 import org.mockito.invocation.Invocation;
 import org.mockito.invocation.Location;
+import org.mockito.invocation.MatchableInvocation;
 
 public class NumberOfInvocationsInOrderChecker {
-    
-    private final Reporter reporter;
-    private final InvocationsFinder finder;
-    private final InvocationMarker invocationMarker = new InvocationMarker();
-    
-    public NumberOfInvocationsInOrderChecker() {
-        this(new InvocationsFinder(), new Reporter());
-    }
-    
-    NumberOfInvocationsInOrderChecker(InvocationsFinder finder, Reporter reporter) {
-        this.finder = finder;
-        this.reporter = reporter;
-    }
-    
-    public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount, InOrderContext context) {
-        List<Invocation> chunk = finder.findMatchingChunk(invocations, wanted, wantedCount, context);
-        
+
+    public void check(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount, InOrderContext context) {
+        List<Invocation> chunk = findMatchingChunk(invocations, wanted, wantedCount, context);
+
         int actualCount = chunk.size();
-        
+
         if (wantedCount > actualCount) {
-            Location lastInvocation = finder.getLastLocation(chunk);
-            reporter.tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
-        } else if (wantedCount < actualCount) {
-            Location firstUndesired = chunk.get(wantedCount).getLocation();
-            reporter.tooManyActualInvocationsInOrder(wantedCount, actualCount, wanted, firstUndesired);
+            Location lastInvocation = getLastLocation(chunk);
+            throw tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
         }
-        
-        invocationMarker.markVerifiedInOrder(chunk, wanted, context);
+        if (wantedCount < actualCount) {
+            Location firstUndesired = chunk.get(wantedCount).getLocation();
+            throw tooManyActualInvocationsInOrder(wantedCount, actualCount, wanted, firstUndesired);
+        }
+
+        markVerifiedInOrder(chunk, wanted, context);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/internal/verification/checkers/package-info.java b/src/main/java/org/mockito/internal/verification/checkers/package-info.java
new file mode 100644
index 0000000..67ec6a9
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/checkers/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Verification checkers.
+ */
+package org.mockito.internal.verification.checkers;
diff --git a/src/main/java/org/mockito/internal/verification/checkers/package.html b/src/main/java/org/mockito/internal/verification/checkers/package.html
deleted file mode 100644
index a248590..0000000
--- a/src/main/java/org/mockito/internal/verification/checkers/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-verification checkers
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/internal/verification/package-info.java b/src/main/java/org/mockito/internal/verification/package-info.java
new file mode 100644
index 0000000..8cdd237
--- /dev/null
+++ b/src/main/java/org/mockito/internal/verification/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Verification logic.
+ */
+package org.mockito.internal.verification;
diff --git a/src/main/java/org/mockito/internal/verification/package.html b/src/main/java/org/mockito/internal/verification/package.html
deleted file mode 100644
index 171df4b..0000000
--- a/src/main/java/org/mockito/internal/verification/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Verification logic.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/invocation/DescribedInvocation.java b/src/main/java/org/mockito/invocation/DescribedInvocation.java
index b182235..fc975ab 100644
--- a/src/main/java/org/mockito/invocation/DescribedInvocation.java
+++ b/src/main/java/org/mockito/invocation/DescribedInvocation.java
@@ -4,12 +4,11 @@
  */
 package org.mockito.invocation;
 
-import org.mockito.exceptions.PrintableInvocation;
 
 /**
  * Provides information about the invocation, specifically a human readable description and the location.
  */
-public interface DescribedInvocation extends PrintableInvocation {
+public interface DescribedInvocation {
 
     /**
      * Describes the invocation in the human friendly way.
diff --git a/src/main/java/org/mockito/invocation/Invocation.java b/src/main/java/org/mockito/invocation/Invocation.java
index 0146697..ca2d29f 100644
--- a/src/main/java/org/mockito/invocation/Invocation.java
+++ b/src/main/java/org/mockito/invocation/Invocation.java
@@ -42,6 +42,14 @@
     Object[] getRawArguments();
 
     /**
+     * Returns unprocessed arguments whereas {@link #getArguments()} returns
+     * arguments already processed (e.g. varargs expended, etc.).
+     *
+     * @return unprocessed arguments, exactly as provided to this invocation.
+     */
+    Class<?> getRawReturnType();
+
+    /**
      * Marks this invocation as verified so that it will not cause verification error at
      * {@link org.mockito.Mockito#verifyNoMoreInteractions(Object...)}
      */
diff --git a/src/main/java/org/mockito/invocation/InvocationOnMock.java b/src/main/java/org/mockito/invocation/InvocationOnMock.java
index 179ae56..345ddb9 100644
--- a/src/main/java/org/mockito/invocation/InvocationOnMock.java
+++ b/src/main/java/org/mockito/invocation/InvocationOnMock.java
@@ -9,33 +9,36 @@
 import java.lang.reflect.Method;
 
 /**
- * An invocation on a mock
+ * An invocation on a mock.
+ *
  * <p>
  * A placeholder for mock, the method that was called and the arguments that were passed.
  */
 public interface InvocationOnMock extends Serializable {
 
     /**
-     * returns the mock object 
-     * 
+     * returns the mock object
+     *
      * @return mock object
      */
     Object getMock();
 
     /**
      * returns the method
-     * 
+     *
      * @return method
      */
     Method getMethod();
 
     /**
-     * returns arguments passed to the method
-     * 
+     * Returns arguments passed to the method.
+     *
+     * Vararg are expanded in this array.
+     *
      * @return arguments
      */
     Object[] getArguments();
-    
+
     /**
      * Returns casted argument at the given index.
      *
@@ -48,22 +51,12 @@
     <T> T getArgument(int index);
 
     /**
-    * Returns casted argument using position
-    * @param index argument position
-    * @param clazz argument type
-    * @return casted argument on position
-    * @deprecated Use getArgument(int) instead.
-    */
-    <T> T getArgumentAt(int index, Class<T> clazz);
-
-
-    /**
      * calls real method
      * <p>
-     * <b>Warning:</b> depending on the real implementation it might throw exceptions  
+     * <b>Warning:</b> depending on the real implementation it might throw exceptions
      *
      * @return whatever the real method returns / throws
-     * @throws Throwable in case real method throws 
+     * @throws Throwable in case real method throws
      */
     Object callRealMethod() throws Throwable;
 }
diff --git a/src/main/java/org/mockito/invocation/MatchableInvocation.java b/src/main/java/org/mockito/invocation/MatchableInvocation.java
new file mode 100644
index 0000000..ff0290a
--- /dev/null
+++ b/src/main/java/org/mockito/invocation/MatchableInvocation.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import org.mockito.ArgumentMatcher;
+
+import java.util.List;
+
+/**
+ * <code>MatchableInvocation</code> wraps {@link Invocation} instance
+ * and holds argument matchers associated with that invocation.
+ * It is used during verification process:
+ *
+ * <pre class="code"><code class="java">
+ *   mock.foo();   // <- invocation
+ *   verify(mock).bar();  // <- matchable invocation
+ * </code></pre>
+ *
+ * @since 2.2.12
+ */
+public interface MatchableInvocation extends DescribedInvocation {
+
+    /**
+     * The actual invocation Mockito will match against.
+     *
+     * @since 2.2.12
+     */
+    Invocation getInvocation();
+
+    /**
+     * The argument matchers of this invocation.
+     * When the invocation is declared without argument matchers (e.g. using plain arguments)
+     * Mockito still converts them into {@link ArgumentMatcher} instances
+     * that use 'eq' matching via {@link org.mockito.Mockito#eq(Object)}.
+     *
+     * @since 2.2.12
+     */
+    List<ArgumentMatcher> getMatchers();
+
+    /**
+     * Same method, mock and all arguments match.
+     *
+     * @since 2.2.12
+     */
+    boolean matches(Invocation candidate);
+
+    /**
+     * Candidate invocation has the similar method.
+     * 'Similar' means the same method name, same mock, unverified, not overloaded, but not necessarily matching arguments
+     *
+     * @since 2.2.12
+     */
+    boolean hasSimilarMethod(Invocation candidate);
+
+    /**
+     * Returns true if the candidate invocation has the same method (method name and parameter types)
+     *
+     * @since 2.2.12
+     */
+    boolean hasSameMethod(Invocation candidate);
+
+    /**
+     * This method is used by Mockito to implement argument captor functionality (see {@link org.mockito.ArgumentCaptor}.
+     * <p>
+     * Makes this instance of matchable invocation capture all arguments of provided invocation.
+     *
+     * @param invocation the invocation to capture the arguments from
+     *
+     * @since 2.2.12
+     */
+    void captureArgumentsFrom(Invocation invocation);
+}
diff --git a/src/main/java/org/mockito/invocation/MockHandler.java b/src/main/java/org/mockito/invocation/MockHandler.java
index bf3aade..1fbdf44 100644
--- a/src/main/java/org/mockito/invocation/MockHandler.java
+++ b/src/main/java/org/mockito/invocation/MockHandler.java
@@ -1,29 +1,29 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.invocation;

-

-import java.io.Serializable;

-

-/**

- * Mockito handler of an invocation on a mock. This is a core part of the API, the heart of Mockito.

- * See also the {@link org.mockito.plugins.MockMaker}.

- * <p>

- * This api is work in progress. Do not provide your own implementations.

- * Mockito will provide you with the implementation via other {@link org.mockito.plugins.MockMaker} methods.

- */

-public interface MockHandler extends Serializable {

-    /**

-     * Takes an invocation object and handles it.

-     * <p>

-     * The default implementation provided by Mockito handles invocations by recording

-     * method calls on mocks for further verification, captures the stubbing information when mock is stubbed,

-     * returns the stubbed values for invocations that have been stubbed, and much more.

-     *

-     * @param invocation The invocation to handle

-     * @return Result

-     * @throws Throwable Throwable

-     */

-    Object handle(Invocation invocation) throws Throwable;

-}

+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import java.io.Serializable;
+
+/**
+ * Mockito handler of an invocation on a mock. This is a core part of the API, the heart of Mockito.
+ * See also the {@link org.mockito.plugins.MockMaker}.
+ * <p>
+ * This api is work in progress. Do not provide your own implementations.
+ * Mockito will provide you with the implementation via other {@link org.mockito.plugins.MockMaker} methods.
+ */
+public interface MockHandler extends Serializable {
+    /**
+     * Takes an invocation object and handles it.
+     * <p>
+     * The default implementation provided by Mockito handles invocations by recording
+     * method calls on mocks for further verification, captures the stubbing information when mock is stubbed,
+     * returns the stubbed values for invocations that have been stubbed, and much more.
+     *
+     * @param invocation The invocation to handle
+     * @return Result
+     * @throws Throwable Throwable
+     */
+    Object handle(Invocation invocation) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/invocation/package-info.java b/src/main/java/org/mockito/invocation/package-info.java
new file mode 100644
index 0000000..f72bb43
--- /dev/null
+++ b/src/main/java/org/mockito/invocation/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Public API related to mock method invocations.
+ */
+package org.mockito.invocation;
diff --git a/src/main/java/org/mockito/invocation/package.html b/src/main/java/org/mockito/invocation/package.html
deleted file mode 100644
index e6742e2..0000000
--- a/src/main/java/org/mockito/invocation/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Public API related to invocation
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/junit/MockitoJUnit.java b/src/main/java/org/mockito/junit/MockitoJUnit.java
index f13b667..2f8b65f 100644
--- a/src/main/java/org/mockito/junit/MockitoJUnit.java
+++ b/src/main/java/org/mockito/junit/MockitoJUnit.java
@@ -1,7 +1,17 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.junit;
 
+import org.mockito.Incubating;
+import org.mockito.quality.Strictness;
+import org.mockito.internal.junit.JUnitRule;
+import org.mockito.internal.junit.VerificationCollectorImpl;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+
 /**
- * The JUnit rule can be used instead of {@link org.mockito.runners.MockitoJUnitRunner}. See {@link MockitoRule}.
+ * The JUnit rule can be used instead of {@link MockitoJUnitRunner}. See {@link MockitoRule}.
  *
  * @since 1.10.17
  */
@@ -9,11 +19,24 @@
 
     /**
      * Creates rule instance that initiates &#064;Mocks
-     * See {@link MockitoRule}.
+     * For more details and examples see {@link MockitoRule}.
      *
      * @return the rule instance
+     * @since 1.10.17
      */
     public static MockitoRule rule() {
-        return new MockitoJUnitRule();
+        return new JUnitRule(new ConsoleMockitoLogger(), Strictness.WARN);
+    }
+
+    /**
+     * Creates a rule instance that can perform lazy verifications.
+     *
+     * @see VerificationCollector
+     * @return the rule instance
+     * @since 2.1.0
+     */
+    @Incubating
+    public static VerificationCollector collector() {
+        return new VerificationCollectorImpl();
     }
 }
diff --git a/src/main/java/org/mockito/junit/MockitoJUnitRule.java b/src/main/java/org/mockito/junit/MockitoJUnitRule.java
deleted file mode 100644
index 7e53273..0000000
--- a/src/main/java/org/mockito/junit/MockitoJUnitRule.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.mockito.junit;
-
-import org.junit.rules.MethodRule;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.Statement;
-import org.mockito.internal.junit.JUnitRule;
-
-
-/**
- * Please use {@link MockitoJUnit#rule()} instead of direct use.
- * The reason of the deprecation is that we want to avoid concrete classes in the public api.
- *
- * @see MockitoJUnit
- * @since 1.10.6
- */
-@Deprecated
-public class MockitoJUnitRule implements MethodRule, MockitoRule {
-    //MethodRule is undeprecated in latest JUnit
-    private final JUnitRule jUnitRule;
-
-    /**
-     * Please use {@link MockitoJUnit#rule()}.
-     * The reason of the deprecation is that we want to avoid concrete classes in the public api.
-     */
-    @Deprecated
-    public MockitoJUnitRule() {
-        this.jUnitRule = new JUnitRule();
-    }
-
-    /**
-     * Please use {@link MockitoJUnit#rule()}.
-     * The reason of the deprecation is that we want to avoid concrete classes in the public api.
-     */
-    @Deprecated
-    public MockitoJUnitRule(Object targetTest) {
-        this();
-    }
-
-    public Statement apply(Statement base, FrameworkMethod method, Object target) {
-        return jUnitRule.apply(base, target);
-    }
-}
diff --git a/src/main/java/org/mockito/junit/MockitoJUnitRunner.java b/src/main/java/org/mockito/junit/MockitoJUnitRunner.java
new file mode 100644
index 0000000..2a15587
--- /dev/null
+++ b/src/main/java/org/mockito/junit/MockitoJUnitRunner.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.junit;
+
+import java.lang.reflect.InvocationTargetException;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.InternalRunner;
+import org.mockito.internal.runners.StrictRunner;
+import org.mockito.quality.MockitoHint;
+import org.mockito.quality.Strictness;
+
+
+/**
+ * Mockito JUnit Runner keeps tests clean and improves debugging experience.
+ * Make sure to try out {@link MockitoJUnitRunner.StrictStubs} which automatically
+ * detects <strong>stubbing argument mismatches</strong> and is planned to be the default in Mockito v3.
+ * Runner is compatible with JUnit 4.4 and higher and adds following behavior:
+ * <ul>
+ *   <li>
+ *       (new since Mockito 2.1.0) Detects unused stubs in the test code.
+ *       See {@link UnnecessaryStubbingException}.
+ *       Similar to JUnit rules, the runner also reports stubbing argument mismatches as console warnings
+ *       (see {@link MockitoHint}).
+ *       To opt-out from this feature, use {@code}&#064;RunWith(MockitoJUnitRunner.Silent.class){@code}
+ *   <li>
+ *      Initializes mocks annotated with {@link Mock},
+ *      so that explicit usage of {@link MockitoAnnotations#initMocks(Object)} is not necessary.
+ *      Mocks are initialized before each test method.
+ *   <li>
+ *      Validates framework usage after each test method. See javadoc for {@link Mockito#validateMockitoUsage()}.
+ *   <li>
+ *      It is highly recommended to use {@link MockitoJUnitRunner.StrictStubs} variant of the runner.
+ *      It drives cleaner tests and improves debugging experience.
+ *      The only reason this feature is not turned on by default
+ *      is because it would have been an incompatible change
+ *      and Mockito strictly follows <a href="http://semver.org">semantic versioning</a>.
+ * </ul>
+ *
+ * Runner is completely optional - there are other ways you can get &#064;Mock working, for example by writing a base class.
+ * Explicitly validating framework usage is also optional because it is triggered automatically by Mockito every time you use the framework.
+ * See javadoc for {@link Mockito#validateMockitoUsage()}.
+ * <p>
+ * Read more about &#064;Mock annotation in javadoc for {@link MockitoAnnotations}
+ * <pre class="code"><code class="java">
+ * <b>&#064;RunWith(MockitoJUnitRunner.StrictStubs.class)</b>
+ * public class ExampleTest {
+ *
+ *     &#064;Mock
+ *     private List list;
+ *
+ *     &#064;Test
+ *     public void shouldDoSomething() {
+ *         list.add(100);
+ *     }
+ * }
+ * </code></pre>
+ *
+ * If you would like to take advantage of Mockito JUnit runner features
+ * but you cannot use the runner because, for example, you use TestNG, there is a solution!
+ * {@link MockitoSession} API is intended to offer cleaner tests and improved debuggability
+ * to users that cannot use Mockito's built-in JUnit support (runner or the rule).
+ */
+public class MockitoJUnitRunner extends Runner implements Filterable {
+
+    /**
+     * This Mockito JUnit Runner implementation *ignores*
+     * stubbing argument mismatches ({@link MockitoJUnitRunner.StrictStubs})
+     * and *does not detect* unused stubbings.
+     * The runner remains 'silent' even if incorrect stubbing is present.
+     * This was the behavior of Mockito JUnit runner in versions 1.x.
+     * Using this implementation of the runner is not recommended.
+     * Engineers should care for removing unused stubbings because they are dead code,
+     * they add unnecessary details, potentially making the test code harder to comprehend.
+     * If you have good reasons to use the silent runner, let us know at the mailing list
+     * or raise an issue in our issue tracker.
+     * The purpose of silent implementation is to satisfy edge/unanticipated use cases,
+     * and to offer users an opt-out.
+     * Mockito framework is opinionated to drive clean tests but it is not dogmatic.
+     * <p>
+     * See also {@link UnnecessaryStubbingException}.
+     * <p>
+     * Usage:
+     * <pre class="code"><code class="java">
+     * <b>&#064;RunWith(MockitoJUnitRunner.Silent.class)</b>
+     * public class ExampleTest {
+     *   // ...
+     * }
+     * </code></pre>
+     *
+     * @since 2.1.0
+     */
+    public static class Silent extends MockitoJUnitRunner {
+        public Silent(Class<?> klass) throws InvocationTargetException {
+            super(new RunnerFactory().create(klass));
+        }
+    }
+
+    /**
+     * Detects unused stubs and reports them as failures. Default behavior in Mockito 2.x.
+     * To improve productivity and quality of tests please consider newer API, the {@link StrictStubs}.
+     * <p>
+     * For more information on detecting unusued stubs, see {@link UnnecessaryStubbingException}.
+     * For more information on stubbing argument mismatch warnings see {@link MockitoHint}.
+     *
+     * @since 2.1.0
+     */
+    public static class Strict extends MockitoJUnitRunner {
+        public Strict(Class<?> klass) throws InvocationTargetException {
+            super(new StrictRunner(new RunnerFactory().createStrict(klass), klass));
+        }
+    }
+
+    /**
+     * Improves debugging tests, helps keeping the tests clean.
+     * Highly recommended to improve productivity and quality of tests.
+     * Planned default behavior for Mockito v3.
+     * Adds behavior equivalent to {@link Strictness#STRICT_STUBS}.
+     * <p>
+     * Usage:
+     * <pre class="code"><code class="java">
+     * <b>&#064;RunWith(MockitoJUnitRunner.StrictStubs.class)</b>
+     * public class ExampleTest {
+     *   // ...
+     * }
+     * </code></pre>
+     *
+     * @since 2.5.1
+     */
+    public static class StrictStubs extends MockitoJUnitRunner {
+        public StrictStubs(Class<?> klass) throws InvocationTargetException {
+            super(new StrictRunner(new RunnerFactory().createStrictStubs(klass), klass));
+        }
+    }
+
+    private final InternalRunner runner;
+
+    public MockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+        //by default, StrictRunner is used. We can change that potentially based on feedback from users
+        this(new StrictRunner(new RunnerFactory().createStrict(klass), klass));
+    }
+
+    MockitoJUnitRunner(InternalRunner runner) throws InvocationTargetException {
+        this.runner = runner;
+    }
+
+    @Override
+    public void run(final RunNotifier notifier) {
+        runner.run(notifier);
+    }
+
+    @Override
+    public Description getDescription() {
+        return runner.getDescription();
+    }
+
+    public void filter(Filter filter) throws NoTestsRemainException {
+        //filter is required because without it UnrootedTests show up in Eclipse
+        runner.filter(filter);
+    }
+}
diff --git a/src/main/java/org/mockito/junit/MockitoRule.java b/src/main/java/org/mockito/junit/MockitoRule.java
index 1778ed6..66ea641 100644
--- a/src/main/java/org/mockito/junit/MockitoRule.java
+++ b/src/main/java/org/mockito/junit/MockitoRule.java
@@ -1,26 +1,59 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.junit;
 
 import org.junit.rules.MethodRule;
+import org.mockito.Incubating;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.MockitoHint;
+import org.mockito.quality.Strictness;
+import org.mockito.exceptions.misusing.PotentialStubbingProblem;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
 
 /**
- * The JUnit rule can be used instead of {@link org.mockito.runners.MockitoJUnitRunner}.
+ * Mockito JUnit Rule helps keeping tests clean.
+ * It initializes mocks, validates usage and detects incorrect stubbing.
+ * Make sure to configure your rule with {@link #strictness(Strictness)} which automatically
+ * detects <strong>stubbing argument mismatches</strong> and is planned to be the default in Mockito v3.
+ * <p>
+ * Since Mockito 2.1.0, JUnit rule emits stubbing warnings and hints to System output (see {@link MockitoHint}).
+ * The JUnit rule can be used instead of {@link MockitoJUnitRunner}.
  * It requires JUnit at least 4.7.
- *
- * This rule adds following behavior:
+ * <p>
+ * The rule adds following behavior:
  * <ul>
  *   <li>
+ *      Since 2.1.0, stubbing warnings and hints are printed to System output.
+ *      Hints contain clickable links that take you right to the line of code that contains a possible problem.
+ *      <strong>Please</strong> give us feedback about the stubbing warnings of JUnit rules in the issue tracker
+ *      (<a href="https://github.com/mockito/mockito/issues/384">issue 384</a>).
+ *      It's a new feature of Mockito 2.1.0. It aims to help debugging tests.
+ *      If you wish the previous behavior, see {@link MockitoRule#silent()}.
+ *      However, we would really like to know why do you wish to silence the warnings!
+ *      See also {@link MockitoHint}.
+ *   <li>
  *      Initializes mocks annotated with {@link org.mockito.Mock},
- *      so that explicit usage of {@link org.mockito.MockitoAnnotations#initMocks(Object)} is not necessary.
+ *      so that explicit usage of {@link MockitoAnnotations#initMocks(Object)} is not necessary.
  *      Mocks are initialized before each test method.
  *   <li>
- *      validates framework usage after each test method. See javadoc for {@link org.mockito.Mockito#validateMockitoUsage()}.
+ *      Validates framework usage after each test method. See javadoc for {@link org.mockito.Mockito#validateMockitoUsage()}.
+ *   <li>
+ *      It is highly recommended to use the rule with {@link #strictness(Strictness)} configured to {@link Strictness#STRICT_STUBS}.
+ *      It drives cleaner tests and improves debugging experience.
+ *      The only reason this feature is not turned on by default
+ *      is because it would have been an incompatible change
+ *      and Mockito strictly follows <a href="http://semver.org">semantic versioning</a>.
+ *
  * </ul>
  * Example use:
  * <pre class="code"><code class="java">
  * public class ExampleTest {
  *
- *     &#064;Rule
- *     public MockitoRule rule = MockitoJUnit.rule();
+ *     //Creating new rule with recommended Strictness setting
+ *     &#064;Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
  *
  *     &#064;Mock
  *     private List list;
@@ -32,6 +65,95 @@
  * }
  * </code></pre>
  *
+ * If you would like to take advantage of Mockito JUnit rule features
+ * but you cannot use the rule because, for example, you use TestNG, there is a solution!
+ * {@link MockitoSession} API is intended to offer cleaner tests and improved debuggability
+ * to users that cannot use Mockito's built-in JUnit support (runner or the rule).
+ *
  * @since 1.10.17
  */
-public interface MockitoRule extends MethodRule {}
+public interface MockitoRule extends MethodRule {
+
+    /**
+     * Rule will not report stubbing warnings during test execution.
+     * By default, stubbing warnings are printed to Standard output to help debugging.
+     * Equivalent of configuring {@link #strictness(Strictness)} with {@link Strictness#LENIENT}.
+     * <p>
+     * <strong>Please</strong> give us feedback about the stubbing warnings of JUnit rules
+     * by commenting on GitHub <a href="https://github.com/mockito/mockito/issues/769">issue 769</a>.
+     * It's a new feature of Mockito 2.1.0. It aims to help debugging tests.
+     * We want to make sure the feature is useful.
+     * We would really like to know why do you wish to silence the warnings!
+     * See also {@link MockitoHint}.
+     * <p>
+     *
+     * Example:
+     * <pre class="code"><code class="java">
+     * public class ExampleTest {
+     *
+     *     &#064;Rule
+     *     public MockitoRule rule = MockitoJUnit.rule().silent();
+     *
+     * }
+     * </code></pre>
+     *
+     * @since 2.1.0
+     */
+    MockitoRule silent();
+
+    /**
+     * The strictness, especially "strict stubs" ({@link Strictness#STRICT_STUBS})
+     * helps debugging and keeping tests clean.
+     * It's a new feature introduced in Mockito 2.3.
+     * Other levels of strictness - "Warn" - current default ({@link Strictness#WARN})
+     * and "lenient" ({@link MockitoRule#silent()}) strictness were already present in Mockito 2.1.0.
+     * Version 2.3.0 introduces "strict stubs" ({@link Strictness#STRICT_STUBS}).
+     *
+     * <pre class="code"><code class="java">
+     * public class ExampleTest {
+     *     &#064;Rule
+     *     public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+     * }
+     * </code></pre>
+     *
+     * How strictness level influences the behavior of JUnit rule:
+     * <ol>
+     *     <li>{@link Strictness#LENIENT} - equivalent of {@link MockitoRule#silent()} -
+     *      no added behavior. The default of Mockito 1.x </li>
+     *     <li>{@link Strictness#WARN} - helps keeping tests clean and with debuggability.
+     *     Reports console warnings about unused stubs
+     *     and stubbing argument mismatches (see {@link MockitoHint}).
+     *     The default of Mockito 2.x</li>
+     *     <li>{@link Strictness#STRICT_STUBS} - ensures clean tests,
+     *     reduces test code duplication, improves debuggability.
+     *     See the details in the Javadoc for {@link Strictness#STRICT_STUBS}.
+     * </ol>
+     *
+     * It is possible to tweak the strictness per test method.
+     * Why would you need it? See the use cases in Javadoc for {@link PotentialStubbingProblem} class.
+     *
+     * <pre class="code"><code class="java">
+     * public class ExampleTest {
+     *     &#064;Rule
+     *     public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+     *
+     *     &#064;Test public void exampleTest() {
+     *         //Change the strictness level only for this test method
+     *         //Useful for edge cases (see Javadoc for PotentialStubbingProblem class)
+     *         mockito.strictness(Strictness.LENIENT);
+     *
+     *         //remaining test code
+     *     }
+     * }
+     * </code></pre>
+     *
+     * "Strict stubs" are tentatively planned to be the default for Mockito v3</li>
+     * We are very eager to hear feedback about "strict stubbing" feature, let us know by commenting on GitHub
+     * <a href="https://github.com/mockito/mockito/issues/769">issue 769</a>.
+     * Strict stubbing is an attempt to improve testability and productivity with Mockito. Tell us what you think!
+     *
+     * @since 2.3.0
+     */
+    @Incubating
+    MockitoRule strictness(Strictness strictness);
+}
diff --git a/src/main/java/org/mockito/junit/VerificationCollector.java b/src/main/java/org/mockito/junit/VerificationCollector.java
new file mode 100644
index 0000000..56d7e14
--- /dev/null
+++ b/src/main/java/org/mockito/junit/VerificationCollector.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.junit;
+
+import org.junit.rules.TestRule;
+import org.mockito.Incubating;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.verification.VerificationMode;
+
+/**
+ * Use this rule in order to collect multiple verification failures and report at once.
+ * This new API in incubating - let us know if you find this feature useful.
+ * Should it be turned on by default with Mockito JUnit Rule?
+ * <p>
+ * Although {@code VerificationCollector} is a JUnit Rule, it does not necessarily have to be used as a Test Rule
+ * - see {@link #collectAndReport()}.
+ * <p>
+ * In the example below, the verification failure thrown by {@code byteReturningMethod()} does not block
+ * verifying against the {@code simpleMethod()}. After the test is run, a report is generated stating all
+ * collect verification failures.
+ *
+ * <pre class="code"><code class="java">
+ *   &#064;Rule
+ *   public VerificationCollector collector = MockitoJUnit.collector();
+ *
+ *   &#064;Test
+ *   public void should_fail() {
+ *       IMethods methods = mock(IMethods.class);
+ *
+ *       verify(methods).byteReturningMethod();
+ *       verify(methods).simpleMethod();
+ *   }
+ * </code></pre>
+ *
+ * @see org.mockito.Mockito#verify(Object)
+ * @see org.mockito.Mockito#verify(Object, VerificationMode)
+ * @since 2.1.0
+ */
+@Incubating
+public interface VerificationCollector extends TestRule {
+
+    /**
+     * Collect all lazily verified behaviour. If there were failed verifications, it will
+     * throw a MockitoAssertionError containing all messages indicating the failed verifications.
+     * <p>
+     * Normally, users don't need to call this method because it is automatically invoked when test finishes
+     * (part of the JUnit Rule behavior).
+     * However, in some circumstances and edge cases, it might be useful to collect and report verification
+     * errors in the middle of the test (for example: some scenario tests or during debugging).
+     *
+     * <pre class="code"><code class="java">
+     *   &#064;Rule
+     *   public VerificationCollector collector = MockitoJUnit.collector();
+     *
+     *   &#064;Test
+     *   public void should_fail() {
+     *       IMethods methods = mock(IMethods.class);
+     *
+     *       verify(methods).byteReturningMethod();
+     *       verify(methods).simpleMethod();
+     *
+     *       //report all verification errors now:
+     *       collector.collectAndReport();
+     *
+     *       //some other test code
+     *   }
+     * </code></pre>
+     *
+     * @throws MockitoAssertionError If there were failed verifications
+     * @since 2.1.0
+     */
+    @Incubating
+    void collectAndReport() throws MockitoAssertionError;
+
+    /**
+     * Enforce all verifications are performed lazily. This method is automatically called when
+     * used as JUnitRule and normally users don't need to use it.
+     * <p>
+     * You should only use this method if you are using a VerificationCollector
+     * inside a method where only this method should be verified lazily. The other methods can
+     * still be verified directly.
+     *
+     * <pre class="code"><code class="java">
+     *   &#064;Test
+     *   public void should_verify_lazily() {
+     *       VerificationCollector collector = MockitoJUnit.collector().assertLazily();
+     *
+     *       verify(methods).byteReturningMethod();
+     *       verify(methods).simpleMethod();
+     *
+     *       collector.collectAndReport();
+     *   }
+     * </code></pre>
+     *
+     * @return this
+     * @since 2.1.0
+     */
+    @Incubating
+    VerificationCollector assertLazily();
+}
diff --git a/src/main/java/org/mockito/junit/package-info.java b/src/main/java/org/mockito/junit/package-info.java
new file mode 100644
index 0000000..d0f74ef
--- /dev/null
+++ b/src/main/java/org/mockito/junit/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito JUnit integration ; rule and runners.
+ */
+package org.mockito.junit;
diff --git a/src/main/java/org/mockito/listeners/InvocationListener.java b/src/main/java/org/mockito/listeners/InvocationListener.java
index 13476e1..699183d 100644
--- a/src/main/java/org/mockito/listeners/InvocationListener.java
+++ b/src/main/java/org/mockito/listeners/InvocationListener.java
@@ -8,21 +8,21 @@
 
 /**
  * This listener can be notified of method invocations on a mock.
- * 
+ *
  * For this to happen, it must be registered using {@link MockSettings#invocationListeners(InvocationListener...)}.
  */
 public interface InvocationListener {
-	
-	/**
-	 * Called after the invocation of the listener's mock if it returned normally.
-	 *
+
+    /**
+     * Called after the invocation of the listener's mock if it returned normally.
+     *
      * <p>
      * Exceptions caused by this invocationListener will raise a {@link org.mockito.exceptions.base.MockitoException}.
      * </p>
-	 *
-	 * @param methodInvocationReport Information about the method call that just happened.
+     *
+     * @param methodInvocationReport Information about the method call that just happened.
      *
      * @see MethodInvocationReport
-	 */
-	void reportInvocation(MethodInvocationReport methodInvocationReport);
+     */
+    void reportInvocation(MethodInvocationReport methodInvocationReport);
 }
diff --git a/src/main/java/org/mockito/listeners/MethodInvocationReport.java b/src/main/java/org/mockito/listeners/MethodInvocationReport.java
index 002233f..a7303e8 100644
--- a/src/main/java/org/mockito/listeners/MethodInvocationReport.java
+++ b/src/main/java/org/mockito/listeners/MethodInvocationReport.java
@@ -2,47 +2,42 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.listeners;

-

-import org.mockito.exceptions.PrintableInvocation;

-import org.mockito.invocation.DescribedInvocation;

-

-/**

- * Represent a method call on a mock.

- *

- * <p>

- *     Contains the information on the mock, the location of the stub

- *     the return value if it returned something (maybe null), or an

- *     exception if one was thrown when the method was invoked.

- * </p>

- */

-public interface MethodInvocationReport {

-    /**

-     * The return type is deprecated, please assign the return value from this method

-     * to the {@link DescribedInvocation} type. Sorry for inconvenience but we had to move

-     * {@link PrintableInvocation} to better place to keep the API consistency.

-     *

-     * @return Information on the method call, never {@code null}

-     */

-    DescribedInvocation getInvocation();

-

-    /**

-     * @return The resulting value of the method invocation, may be <code>null</code>

-     */

-    Object getReturnedValue();

-

-    /**

-     * @return The throwable raised by the method invocation, maybe <code>null</code>

-     */

-    Throwable getThrowable();

-

-    /**

-     * @return <code>true</code> if an exception was raised, <code>false</code> otherwise

-     */

-    boolean threwException();

-

-    /**

-     * @return Location of the stub invocation

-     */

-    String getLocationOfStubbing();

-}

+package org.mockito.listeners;
+
+import org.mockito.invocation.DescribedInvocation;
+
+/**
+ * Represent a method call on a mock.
+ *
+ * <p>
+ *     Contains the information on the mock, the location of the stub
+ *     the return value if it returned something (maybe null), or an
+ *     exception if one was thrown when the method was invoked.
+ * </p>
+ */
+public interface MethodInvocationReport {
+    /**
+     * @return Information on the method call, never {@code null}
+     */
+    DescribedInvocation getInvocation();
+
+    /**
+     * @return The resulting value of the method invocation, may be <code>null</code>
+     */
+    Object getReturnedValue();
+
+    /**
+     * @return The throwable raised by the method invocation, maybe <code>null</code>
+     */
+    Throwable getThrowable();
+
+    /**
+     * @return <code>true</code> if an exception was raised, <code>false</code> otherwise
+     */
+    boolean threwException();
+
+    /**
+     * @return Location of the stub invocation
+     */
+    String getLocationOfStubbing();
+}
diff --git a/src/main/java/org/mockito/listeners/MockCreationListener.java b/src/main/java/org/mockito/listeners/MockCreationListener.java
new file mode 100644
index 0000000..24a1904
--- /dev/null
+++ b/src/main/java/org/mockito/listeners/MockCreationListener.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.listeners;
+
+import org.mockito.mock.MockCreationSettings;
+
+/**
+ * Notified when mock object is created.
+ * For more information on listeners see {@link org.mockito.MockitoFramework#addListener(MockitoListener)}.
+ */
+public interface MockCreationListener extends MockitoListener {
+
+    /**
+     * Mock object was just created.
+     *
+     * @param mock created mock object
+     * @param settings the settings used for creation
+     */
+    void onMockCreated(Object mock, MockCreationSettings settings);
+}
diff --git a/src/main/java/org/mockito/listeners/MockitoListener.java b/src/main/java/org/mockito/listeners/MockitoListener.java
new file mode 100644
index 0000000..ea8dcb6
--- /dev/null
+++ b/src/main/java/org/mockito/listeners/MockitoListener.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.listeners;
+
+/**
+ * Marker interface for all types of Mockito listeners.
+ * For more information, see {@link org.mockito.MockitoFramework#addListener(MockitoListener)}.
+ */
+public interface MockitoListener {
+}
diff --git a/src/main/java/org/mockito/listeners/VerificationListener.java b/src/main/java/org/mockito/listeners/VerificationListener.java
new file mode 100644
index 0000000..0bc3867
--- /dev/null
+++ b/src/main/java/org/mockito/listeners/VerificationListener.java
@@ -0,0 +1,20 @@
+package org.mockito.listeners;
+
+import org.mockito.Incubating;
+import org.mockito.verification.VerificationEvent;
+
+/**
+ * This listener can be notified of verify invocations on a mock.
+ * <p>
+ * For this to happen, it must be registered using {@link org.mockito.internal.progress.MockingProgress#addListener(MockitoListener)}.
+ */
+@Incubating
+public interface VerificationListener extends MockitoListener {
+    /**
+     * Called after a verification happened.
+     * This includes verifications that fail due to the verification mode failing.
+     *
+     * @param verificationEvent the event that occurred.
+     */
+    void onVerification(VerificationEvent verificationEvent);
+}
diff --git a/src/main/java/org/mockito/listeners/package-info.java b/src/main/java/org/mockito/listeners/package-info.java
new file mode 100644
index 0000000..51f5f1b
--- /dev/null
+++ b/src/main/java/org/mockito/listeners/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Public classes relative to the listener APIs.
+ */
+package org.mockito.listeners;
diff --git a/src/main/java/org/mockito/listeners/package.html b/src/main/java/org/mockito/listeners/package.html
deleted file mode 100644
index 098d0ed..0000000
--- a/src/main/java/org/mockito/listeners/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--

-  ~ Copyright (c) 2007 Mockito contributors

-  ~ This program is made available under the terms of the MIT License.

-  -->

-

-<body>

-Public classes relative to the call listener.

-</body>

diff --git a/src/main/java/org/mockito/mock/MockCreationSettings.java b/src/main/java/org/mockito/mock/MockCreationSettings.java
index 6b91a47..f27d481 100644
--- a/src/main/java/org/mockito/mock/MockCreationSettings.java
+++ b/src/main/java/org/mockito/mock/MockCreationSettings.java
@@ -25,7 +25,7 @@
     /**
      * the extra interfaces the mock object should implement.
      */
-    Set<Class> getExtraInterfaces();
+    Set<Class<?>> getExtraInterfaces();
 
     /**
      * the name of this mock, as printed on verification errors; see {@link org.mockito.MockSettings#name}.
@@ -35,7 +35,7 @@
     /**
      * the default answer for this mock, see {@link org.mockito.MockSettings#defaultAnswer}.
      */
-    Answer getDefaultAnswer();
+    Answer<?> getDefaultAnswer();
 
     /**
      * the spied instance - needed for spies.
@@ -80,4 +80,4 @@
      */
     @Incubating
     Object getOuterClassInstance();
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/mock/SerializableMode.java b/src/main/java/org/mockito/mock/SerializableMode.java
index d10b1d6..790fc04 100644
--- a/src/main/java/org/mockito/mock/SerializableMode.java
+++ b/src/main/java/org/mockito/mock/SerializableMode.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.mock;
 
 import org.mockito.Incubating;
@@ -23,4 +27,4 @@
      */
     @Incubating
     ACROSS_CLASSLOADERS
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/mock/package-info.java b/src/main/java/org/mockito/mock/package-info.java
new file mode 100644
index 0000000..172e1e7
--- /dev/null
+++ b/src/main/java/org/mockito/mock/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mock settings related classes.
+ */
+package org.mockito.mock;
diff --git a/src/main/java/org/mockito/package-info.java b/src/main/java/org/mockito/package-info.java
new file mode 100644
index 0000000..d5dc5c0
--- /dev/null
+++ b/src/main/java/org/mockito/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito is a mock library for java - see {@link org.mockito.Mockito} class for for usage.
+ *
+ * @see org.mockito.Mockito
+ */
+package org.mockito;
diff --git a/src/main/java/org/mockito/package.html b/src/main/java/org/mockito/package.html
deleted file mode 100644
index e54efb3..0000000
--- a/src/main/java/org/mockito/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Mockito is a mock library for java - see Mockito class for for usage.
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/plugins/AnnotationEngine.java b/src/main/java/org/mockito/plugins/AnnotationEngine.java
new file mode 100644
index 0000000..c60f477
--- /dev/null
+++ b/src/main/java/org/mockito/plugins/AnnotationEngine.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.plugins;
+
+/**
+ * Configures test via annotations.
+ *
+ * <p>Mockito default engine handles the logic behind &#064;Mock, &#064;Captor, &#064;Spy and &#064;InjectMocks annotations.
+ *
+ * <p>This interface is an extension point that make possible to use a different annotation engine allowing to extend
+ * or replace mockito default engine.
+ *
+ * <p>
+ * If you are interested then see implementations or source code of {@link org.mockito.MockitoAnnotations#initMocks(Object)}
+ *
+ * <p>This plugin mechanism supersedes the {@link org.mockito.configuration.IMockitoConfiguration}
+ * in regard of switching mockito components.
+ */
+public interface AnnotationEngine {
+    /**
+     * Processes the test instance to configure annotated members.
+     *
+     * @param clazz Class where to extract field information, check implementation for details
+     * @param testInstance Test instance
+     */
+    void process(Class<?> clazz, Object testInstance);
+}
diff --git a/src/main/java/org/mockito/plugins/InstantiatorProvider.java b/src/main/java/org/mockito/plugins/InstantiatorProvider.java
new file mode 100644
index 0000000..b776f6e
--- /dev/null
+++ b/src/main/java/org/mockito/plugins/InstantiatorProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.plugins;
+
+import org.mockito.internal.creation.instance.Instantiator;
+import org.mockito.mock.MockCreationSettings;
+
+/**
+ * <p>
+ *     Mockito will invoke this interface in order to fetch an instance instantiator provider.
+ * </p>
+ *
+ * <p>
+ *     By default, an internal byte-buddy/asm/objenesis based implementation is used.
+ * </p>
+ *
+ * <h3>Using the extension point</h3>
+ *
+ * <p>
+ *     The plugin mechanism of mockito works in a similar way as the
+ *     {@link java.util.ServiceLoader}, however instead of looking in the <code>META-INF</code>
+ *     directory, Mockito will look in <code>mockito-extensions</code> directory.
+ *     <em>The reason for that is that Android SDK strips jar from the <code>META-INF</code>
+ *     directory when creating an APK.</em>
+ * </p>
+ *
+ * <ol style="list-style-type: lower-alpha">
+ *     <li>The implementation itself, for example
+ *         <code>org.awesome.mockito.AwesomeInstantiatorProvider</code> that implements the
+ *         <code>InstantiatorProvider</code>.</li>
+ *     <li>A file "<code>mockito-extensions/org.mockito.plugins.InstantiatorProvider</code>".
+ *         The content of this file is exactly a <strong>one</strong> line with the qualified
+ *         name: <code>org.awesome.mockito.AwesomeInstantiatorProvider</code>.</li>
+ * </ol></p>
+ *
+ * <p>
+ *     Note that if several <code>mockito-extensions/org.mockito.plugins.InstantiatorProvider</code>
+ *     files exists in the classpath, Mockito will only use the first returned by the standard
+ *     {@link ClassLoader#getResource} mechanism.
+ * <p>
+ *     So just create a custom implementation of {@link InstantiatorProvider} and place the
+ *     qualified name in the following file
+ *     <code>mockito-extensions/org.mockito.plugins.InstantiatorProvider</code>.
+ * </p>
+ *
+ * @since 21.10.15
+ */
+public interface InstantiatorProvider {
+
+    /**
+     * Returns an instantiator, used to create new class instances.
+     */
+    Instantiator getInstantiator(MockCreationSettings<?> settings);
+}
diff --git a/src/main/java/org/mockito/plugins/MockMaker.java b/src/main/java/org/mockito/plugins/MockMaker.java
index 242c273..e4b0ca8 100644
--- a/src/main/java/org/mockito/plugins/MockMaker.java
+++ b/src/main/java/org/mockito/plugins/MockMaker.java
@@ -4,16 +4,17 @@
  */
 package org.mockito.plugins;
 
+import org.mockito.Incubating;
 import org.mockito.invocation.MockHandler;
 import org.mockito.mock.MockCreationSettings;
 
 /**
  * The facility to create mocks.
  *
- * <p>By default, an internal cglib/asm/objenesis based implementation is used.</p>
+ * <p>By default, an internal byte-buddy/asm/objenesis based implementation is used.</p>
  *
  * <p>{@code MockMaker} is an extension point that makes it possible to use custom dynamic proxies
- * and avoid using the default cglib/asm/objenesis implementation.
+ * and avoid using the default byte-buddy/asm/objenesis implementation.
  * For example, the android users can use a MockMaker that can work with Dalvik virtual machine
  * and hence bring Mockito to android apps developers.</p>
  *
@@ -22,10 +23,17 @@
  * <p>Suppose you wrote an extension to create mocks with some <em>Awesome</em> library, in order to tell
  * Mockito to use it you need to put in your <strong>classpath</strong>:
  * <ol style="list-style-type: lower-alpha">
- *     <li>The implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code> that extends the <code>MockMaker</code>.</li>
- *     <li>A file "<code>mockito-extensions/org.mockito.plugins.MockMaker</code>". The content of this file is
- *     exactly a <strong>one</strong> line with the qualified name: <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
- * </ol></p>
+ *     <li>
+ *         The implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code> that
+ *         extends the <code>MockMaker</code>.
+ *     </li>
+ *     <li>
+ *         A file "<code>mockito-extensions/org.mockito.plugins.MockMaker</code>". The content of this file is
+ *         exactly a <strong>one</strong> line with the qualified name:
+ *         <code>org.awesome.mockito.AwesomeMockMaker</code>.
+*      </li>
+ * </ol>
+ * </p>
  *
  * <p>Note that if several <code>mockito-extensions/org.mockito.plugins.MockMaker</code> files exists in the classpath
  * Mockito will only use the first returned by the standard {@link ClassLoader#getResource} mechanism.
@@ -48,7 +56,7 @@
      *     </li>
      * </ul>
      *
-     * @param settings - mock creation settings like type to mock, extra interfaces and so on.
+     * @param settings Mock creation settings like type to mock, extra interfaces and so on.
      * @param handler See {@link org.mockito.invocation.MockHandler}.
      *                <b>Do not</b> provide your own implementation at this time. Make sure your implementation of
      *                {@link #getHandler(Object)} will return this instance.
@@ -67,7 +75,7 @@
      * Use the instance provided to you by Mockito at {@link #createMock} or {@link #resetMock}.
      *
      * @param mock The mock instance.
-     * @return may return null - it means that there is no handler attached to provided object.
+     * @return The mock handler, but may return null - it means that there is no handler attached to provided object.
      *   This means the passed object is not really a Mockito mock.
      * @since 1.9.5
      */
@@ -92,4 +100,36 @@
             MockHandler newHandler,
             MockCreationSettings settings
     );
-}
\ No newline at end of file
+
+    /**
+     * Indicates if the given type can be mocked by this mockmaker.
+     *
+     * <p>Mockmaker may have different capabilities in term of mocking, typically
+     * Mockito 1.x's internal mockmaker cannot mock final types. Other implementations, may
+     * have different limitations.</p>
+     *
+     * @param type The type inspected for mockability.
+     * @return object that carries the information about mockability of given type.
+     * @since 2.1.0
+     */
+    @Incubating
+    TypeMockability isTypeMockable(Class<?> type);
+
+    /**
+     * Carries the mockability information
+     *
+     * @since 2.1.0
+     */
+    @Incubating
+    interface TypeMockability {
+        /**
+         * informs if type is mockable
+         */
+        boolean mockable();
+
+        /**
+         * informs why type is not mockable
+         */
+        String nonMockableReason();
+    }
+}
diff --git a/src/main/java/org/mockito/plugins/PluginSwitch.java b/src/main/java/org/mockito/plugins/PluginSwitch.java
index 4c08974..916db24 100644
--- a/src/main/java/org/mockito/plugins/PluginSwitch.java
+++ b/src/main/java/org/mockito/plugins/PluginSwitch.java
@@ -1,12 +1,44 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.plugins;
 
 import org.mockito.Incubating;
 
 /**
  * Allows switching off the plugins that are discovered on classpath.
- * When a particular plugin is switched off, the default Mockito behavior is used.
- * For example, if Android's dexmaker MockMaker is switched off,
- * Mockito default MockMaker implementation is used {@link org.mockito.plugins.MockMaker}
+ *
+ * <p>
+ *     Mockito will invoke this interface in order to select whether a plugin is enabled or not.
+ * </p>
+ *
+ * <p>
+ *     When a particular plugin is switched off, the default Mockito behavior is used.
+ *     For example, if Android's dexmaker MockMaker is switched off,
+ *     Mockito default MockMaker implementation is used {@link org.mockito.plugins.MockMaker}
+ * </p>
+ *
+ * <h3>Using the extension point</h3>
+ *
+ * <p>
+ *     The plugin mechanism of mockito works in a similar way as the {@link java.util.ServiceLoader}, however instead of
+ *     looking in the <code>META-INF</code> directory, Mockito will look in <code>mockito-extensions</code> directory.
+ *     <em>The reason for that is that Android SDK strips jar from the <code>META-INF</code> directory when creating an APK.</em>
+ * </p>
+ *
+ * <ol style="list-style-type: lower-alpha">
+ *     <li>The implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code> that extends the <code>MockMaker</code>.</li>
+ *     <li>A file "<code>mockito-extensions/org.mockito.plugins.MockMaker</code>". The content of this file is
+ *     exactly a <strong>one</strong> line with the qualified name: <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
+ * </ol></p>
+ *
+ * <p>Note that if several <code>mockito-extensions/org.mockito.plugins.MockMaker</code> files exists in the classpath
+ * Mockito will only use the first returned by the standard {@link ClassLoader#getResource} mechanism.
+ * <p>
+ *     So just create a custom implementation of {@link PluginSwitch} and place the qualified name in the following file
+ *     <code>mockito-extensions/org.mockito.plugins.PluginSwitch</code>.
+ * </p>
  *
  * @since 1.10.15
  */
@@ -21,4 +53,4 @@
      * @since 1.10.15
      */
     boolean isEnabled(String pluginClassName);
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/plugins/StackTraceCleanerProvider.java b/src/main/java/org/mockito/plugins/StackTraceCleanerProvider.java
index 1671795..61761a3 100644
--- a/src/main/java/org/mockito/plugins/StackTraceCleanerProvider.java
+++ b/src/main/java/org/mockito/plugins/StackTraceCleanerProvider.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.plugins;
 
 import org.mockito.exceptions.stacktrace.StackTraceCleaner;
@@ -21,4 +25,4 @@
      * @return StackTraceCleaner to use
      */
     StackTraceCleaner getStackTraceCleaner(StackTraceCleaner defaultCleaner);
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/mockito/plugins/package-info.java b/src/main/java/org/mockito/plugins/package-info.java
new file mode 100644
index 0000000..194a136
--- /dev/null
+++ b/src/main/java/org/mockito/plugins/package-info.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito plugins allow customization of behavior.
+ * For example, it is useful for Android integration via dexmaker.
+ * See examples in docs for MockMaker.
+ *
+ * <p>
+ * The plugin mechanism of mockito works in a similar way as the {@link java.util.ServiceLoader}, however instead of
+ * looking in the <code>META-INF</code> directory, Mockito will look in <code>mockito-extensions</code> directory.
+ * <em>The reason for that is that Android SDK strips jars from the <code>META-INF</code> directory when creating an APK.</em>
+ * </p>
+ *
+ * <p>
+ * For example :
+ * </p>
+ *
+ * <ol style="list-style-type: lower-alpha">
+ * <li>
+ * Create implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code> that extends
+ * the <code>MockMaker</code>.
+ * </li>
+ * <li>
+ * A file "<code>mockito-extensions/org.mockito.plugins.MockMaker</code>". The content of this file is exactly
+ * a <strong>one</strong> line with the qualified name: <code>org.awesome.mockito.AwesomeMockMaker</code>.
+ * </li>
+ * </ol>
+ *
+ * <p>
+ * Note that if several <code>mockito-extensions/org.mockito.plugins.MockMaker</code> files exists in the classpath
+ * Mockito will only use the first returned by the standard <code>ClassLoader.getResource</code> mechanism.
+ * </p>
+ */
+package org.mockito.plugins;
diff --git a/src/main/java/org/mockito/plugins/package.html b/src/main/java/org/mockito/plugins/package.html
deleted file mode 100644
index 72e0d04..0000000
--- a/src/main/java/org/mockito/plugins/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-Mockito plugins allow customization of behavior.
-For example, it is useful for Android integration via dexmaker.
-See examples in docs for MockMaker.
-</body>
diff --git a/src/main/java/org/mockito/quality/MockitoHint.java b/src/main/java/org/mockito/quality/MockitoHint.java
new file mode 100644
index 0000000..d752159
--- /dev/null
+++ b/src/main/java/org/mockito/quality/MockitoHint.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.quality;
+
+import org.mockito.MockitoSession;
+import org.mockito.junit.MockitoJUnitRunner;
+
+/**
+ * To improve productivity when writing Java tests
+ * stubbing hints and warnings are printed to standard output.
+ * See also "strict stubbing" API ({@link Strictness})
+ * which drives cleaner tests and productivity more effectively than Mockito hints.
+ * <p>
+ * Hints contain clickable links that take you right to the line of code that contains a possible problem.
+ * Those are hints - they not necessarily indicate real problems 100% of the time.
+ * This way the developer can:
+ * <ol>
+ *   <li>produce cleaner tests - by detecting and removing unused stubs</li>
+ *   <li>understand why test fails - by detecting stubs that were ineffective due to argument mismatch</li>
+ * </ol>
+ * We would appreciate feedback about this feature so that we can make Mockito better!
+ * Our goal is to provide maximum productivity when testing Java.
+ * Join the discussion in <a href="https://github.com/mockito/mockito/issues/384">issue 384</a>.
+ * <p>
+ * How to take advantage of the hints? Use:
+ * <ul>
+ *     <li>{@link org.mockito.junit.MockitoJUnit#rule()}</li>
+ *     <li>{@link MockitoJUnitRunner}</li>
+ *     <li>{@link MockitoSession}</li>
+ * </ul>
+ *
+ * <h3>Cleaner tests without unnecessary stubs</h3>
+ * Unnecessary stubs are stubbed method calls that were never realized during test execution.
+ * To find out more and see the example test code, see {@link org.mockito.exceptions.misusing.UnnecessaryStubbingException}.
+ *
+ * <h3>Better failure diagnostics by detecting mismatched stubs</h3>
+ *
+ * When the test fails for a wrong reason, sometimes it's because stubbed method was called with incorrect argument(s).
+ * In this scenario, the problem is not often obvious.
+ * Hence, Mockito generates a hint to the standard output indicating this scenario.
+ * Hint contains a clickable link to the line of code where the potential problem is.
+ * <p>
+ * Example:
+ *
+ * <p>
+ * Let's say the test fails on assertion.
+ * Let's say the underlying reason is a stubbed method that was called with different arguments:
+ * <pre class="code"><code class="java">
+ * //test:
+ * Dictionary dictionary = new Dictionary(translator);
+ * when(translator.translate("Mockito")).thenReturn("cool framework");
+ * String translated = dictionary.search("Mockito");
+ * assertEquals("cool framework", translated);
+ *
+ * //code:
+ * public String search(String word) {
+ *     ...
+ *     return translator.translate("oups");
+ *
+ * </code></pre>
+ * On standard output you'll see a hint with clickable links to both locations:
+ * a) stubbing declaration and b) the method call on a stub with mismatched argument.
+ * <p>
+ * Note that it is just a warning, not an assertion.
+ * The test fails on assertion because it is the assertion's duty
+ * to document what the test stands for and what behavior it proves.
+ * Hints just makes it quicker to figure out if the test fails for the right reason.
+ * <p>
+ * Feedback is very welcome at <a href="https://github.com/mockito/mockito/issues/384">issue 384</a>.
+ *
+ * @since 2.1.0
+ */
+public interface MockitoHint {
+}
diff --git a/src/main/java/org/mockito/quality/Strictness.java b/src/main/java/org/mockito/quality/Strictness.java
new file mode 100644
index 0000000..0c84068
--- /dev/null
+++ b/src/main/java/org/mockito/quality/Strictness.java
@@ -0,0 +1,88 @@
+package org.mockito.quality;
+
+import org.mockito.Incubating;
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.misusing.PotentialStubbingProblem;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.internal.junit.JUnitRule;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+/**
+ * Configures the "strictness" of Mockito during a mocking session.
+ * A session typically maps to a single test method invocation.
+ * {@code Strictness} drives cleaner tests and better productivity.
+ * The easiest way to leverage enhanced {@code Strictness} is using
+ * Mockito's JUnit support ({@link MockitoRule} or {@link MockitoJUnitRunner}).
+ * If you cannot use JUnit support {@link MockitoSession} is the way to go.
+ * <p>
+ * How strictness level influences the behavior of the test (mocking session)?
+ * <ol>
+ *     <li>{@link Strictness#LENIENT} - no added behavior.
+ *       The default of Mockito 1.x.
+ *       Recommended only if you cannot use {@link #STRICT_STUBS} nor {@link #WARN}.</li>
+ *     <li>{@link Strictness#WARN} - helps keeping tests clean and improves debuggability.
+ *       Reports console warnings about unused stubs
+ *       and stubbing argument mismatch (see {@link org.mockito.quality.MockitoHint}).
+ *       The default behavior of Mockito 2.x when {@link JUnitRule} or {@link MockitoJUnitRunner} are used.</li>
+ *       Recommended if you cannot use {@link #STRICT_STUBS}.
+ *     <li>{@link Strictness#STRICT_STUBS} - ensures clean tests, reduces test code duplication, improves debuggability.
+ *       Best combination of flexibility and productivity. Highly recommended.
+ *       Planned as default for Mockito v3.
+ *       See {@link #STRICT_STUBS} for the details.
+ * </ol>
+ *
+ * @since 2.3.0
+ */
+@Incubating
+public enum Strictness {
+
+    /**
+     * No extra strictness. Mockito 1.x behavior.
+     * Recommended only if you cannot use {@link #STRICT_STUBS} nor {@link #WARN}.
+     * <p>
+     * For more information see {@link Strictness}.
+     *
+     * @since 2.3.0
+     */
+    @Incubating
+    LENIENT,
+
+    /**
+     * Helps keeping tests clean and improves debuggability.
+     * Extra warnings emitted to the console, see {@link MockitoHint}.
+     * Default Mockito 2.x behavior.
+     * Recommended if you cannot use {@link #STRICT_STUBS}.
+     * <p>
+     * For more information see {@link Strictness}.
+     *
+     * @since 2.3.0
+     */
+    @Incubating
+    WARN,
+
+    /**
+     * Ensures clean tests, reduces test code duplication, improves debuggability.
+     * Offers best combination of flexibility and productivity.
+     * Highly recommended.
+     * Planned as default for Mockito v3.
+     * <p>
+     * Adds following behavior:
+     *  <ul>
+     *      <li>Improved productivity: the test fails early when code under test invokes
+     *          stubbed method with different arguments (see {@link PotentialStubbingProblem}).</li>
+     *      <li>Cleaner tests without unnecessary stubbings:
+     *          the test fails when unused stubs are present (see {@link UnnecessaryStubbingException}).</li>
+     *      <li>Cleaner, more DRY tests ("Don't Repeat Yourself"):
+     *          If you use {@link org.mockito.Mockito#verifyNoMoreInteractions(Object...)}
+     *          you no longer need to explicitly verify stubbed invocations.
+     *          They are automatically verified for you.</li>
+     *  </ul>
+     *
+     * For more information see {@link Strictness}.
+     *
+     * @since 2.3.0
+     */
+    @Incubating
+    STRICT_STUBS;
+}
diff --git a/src/main/java/org/mockito/quality/package-info.java b/src/main/java/org/mockito/quality/package-info.java
new file mode 100644
index 0000000..6f14af9
--- /dev/null
+++ b/src/main/java/org/mockito/quality/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mocking quality related classes.
+ */
+package org.mockito.quality;
diff --git a/src/main/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java b/src/main/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java
index 2dfdab0..522b795 100644
--- a/src/main/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java
+++ b/src/main/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java
@@ -1,132 +1,73 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.runners;

-

-import org.junit.runner.Description;

-import org.junit.runner.Runner;

-import org.junit.runner.manipulation.Filter;

-import org.junit.runner.manipulation.Filterable;

-import org.junit.runner.manipulation.NoTestsRemainException;

-import org.junit.runner.notification.Failure;

-import org.junit.runner.notification.RunListener;

-import org.junit.runner.notification.RunNotifier;

-import org.junit.runners.BlockJUnit4ClassRunner;

-import org.mockito.internal.debugging.WarningsCollector;

-import org.mockito.internal.runners.RunnerFactory;

-import org.mockito.internal.runners.RunnerImpl;

-import org.mockito.internal.util.ConsoleMockitoLogger;

-import org.mockito.internal.util.MockitoLogger;

-

-import java.lang.reflect.InvocationTargetException;

-

-/**

- * Uses <b>JUnit 4.5</b> runner {@link BlockJUnit4ClassRunner}.

- * <p>

- * Experimental implementation that suppose to improve tdd/testing experience. 

- * Don't hesitate to send feedback to mockito@googlegroups.com

- * <b>It is very likely it will change in the next version!</b>

- * <p>

- * This runner does exactly what {@link MockitoJUnitRunner} does but also  

- * prints warnings that might be useful. 

- * The point is that Mockito should help the tdd developer to quickly figure out if the test fails for the right reason. 

- * Then the developer can implement the functionality. 

- * Also when the test fails it should be easy to figure out why the test fails. 

- * <p>

- * Sometimes when the test fails, the underlying reason is that stubbed method was called with wrong arguments. 

- * Sometimes it fails because one forgets to stub a method or forgets to call a stubbed method. 

- * All above problems are not immediately obvious.

- * <p>

- * One way of approaching this problem is full-blown 'expect' API. 

- * However it means the 'expectations upfront' business which is not in line with core Mockito concepts.

- * After all, the essence of testing are <b>explicit assertions</b> that are described consistently at the <b>bottom of the test</b> method.

- * <p>

- * Here's the experiment: a warning is printed to the standard output if the test fails.

- * Also, you get a clickabe link to the line of code. You can immediately jump to the place in code where the potential problem is.

- * <p> 

- * Let's say your test fails on assertion. 

- * Let's say the underlying reason is a stubbed method that was called with different arguments:

- * <pre class="code"><code class="java">

- * //test:

- * Dictionary dictionary = new Dictionary(translator);

- * when(translator.translate("Mockito")).thenReturn("cool framework");

- * String translated = dictionary.search("Mockito");

- * assertEquals("cool framework", translated);

- * 

- * //code:

- * public String search(String word) {

- *     ...

- *     return translator.translate("oups");

- *

- * </code></pre>

- * On standard output you'll see something like that:

- * <pre class="code"><code class="java">

- * [Mockito] Warning - stubbed method called with different arguments.

- * Stubbed this way:

- * translator.translate("Mockito");

- * org.dictionary.SmartDictionaryTest.shouldFindTranslation(SmartDictionaryTest.java:27)

- *  

- * But called with different arguments:

- * translator.translate("oups");

- * org.dictionary.SmartDictionary.search(SmartDictionary.java:15)

- * </code></pre>

- * <p>

- * Note that it is just a warning, not an assertion. 

- * The test fails on assertion because it's the assertion's duty to document what the test stands for and what behavior it proves. 

- * Warnings just makes it quicker to figure out if the test fails for the right reason.

- * <p>

- * Note that code links printed to the console are clickable in any decent IDE (e.g. Eclipse).

- * <p>

- * So far I identified 2 cases when warnings are printed:

- * <li>unsued stub</li>

- * <li>stubbed method but called with different arguments</li> 

- * <p>

- * <br/>

- * <p>

- * Do you think it is useful or not? Drop us an email at mockito@googlegroups.com

- */

-public class ConsoleSpammingMockitoJUnitRunner extends Runner implements Filterable {

-

-    private final MockitoLogger logger;

-    private final RunnerImpl runner;

-    

-    public ConsoleSpammingMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {

-        this(new ConsoleMockitoLogger(), new RunnerFactory().create(klass));

-    }

-    

-    ConsoleSpammingMockitoJUnitRunner(MockitoLogger logger, RunnerImpl runnerImpl) {

-        this.runner = runnerImpl;

-        this.logger = logger;

-    }

-    

-    @Override

-    public void run(RunNotifier notifier) {

-        RunListener listener = new RunListener() {

-            WarningsCollector warningsCollector;

-            

-            @Override

-            public void testStarted(Description description) throws Exception {

-                warningsCollector = new WarningsCollector();

-            }

-            

-            @Override public void testFailure(Failure failure) throws Exception {                

-                logger.log(warningsCollector.getWarnings());

-            }

-        };

-

-        notifier.addListener(listener);

-

-        runner.run(notifier);

-    }

-

-    @Override

-    public Description getDescription() {

-        return runner.getDescription();

-    }

-    

-    public void filter(Filter filter) throws NoTestsRemainException {

-        //filter is required because without it UnrootedTests show up in Eclipse

-        runner.filter(filter);

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.internal.debugging.WarningsCollector;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.InternalRunner;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+import org.mockito.internal.util.MockitoLogger;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @deprecated as of 2.1.0. Use the {@link org.mockito.junit.MockitoJUnitRunner} runner instead
+ * which contains support for detecting unused stubs.
+ * <p>
+ * If you still prefer using this runner, tell us why (create ticket in our issue tracker).
+ */
+@Deprecated
+public class ConsoleSpammingMockitoJUnitRunner extends Runner implements Filterable {
+
+    private final MockitoLogger logger;
+    private final InternalRunner runner;
+
+    public ConsoleSpammingMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+        this(new ConsoleMockitoLogger(), new RunnerFactory().create(klass));
+    }
+
+    ConsoleSpammingMockitoJUnitRunner(MockitoLogger logger, InternalRunner runner) {
+        this.runner = runner;
+        this.logger = logger;
+    }
+
+    @Override
+    public void run(RunNotifier notifier) {
+        RunListener listener = new RunListener() {
+            WarningsCollector warningsCollector;
+
+            @Override
+            public void testStarted(Description description) throws Exception {
+                warningsCollector = new WarningsCollector();
+            }
+
+            @Override public void testFailure(Failure failure) throws Exception {
+                logger.log(warningsCollector.getWarnings());
+            }
+        };
+
+        notifier.addListener(listener);
+
+        runner.run(notifier);
+    }
+
+    @Override
+    public Description getDescription() {
+        return runner.getDescription();
+    }
+
+    public void filter(Filter filter) throws NoTestsRemainException {
+        //filter is required because without it UnrootedTests show up in Eclipse
+        runner.filter(filter);
+    }
+}
diff --git a/src/main/java/org/mockito/runners/MockitoJUnit44Runner.java b/src/main/java/org/mockito/runners/MockitoJUnit44Runner.java
deleted file mode 100644
index 4080d1e..0000000
--- a/src/main/java/org/mockito/runners/MockitoJUnit44Runner.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-
-package org.mockito.runners;
-
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * <b>Deprecated: Simply use {@link MockitoJUnitRunner}</b>
- * <p>
- * Compatible only with <b>JUnit 4.4</b>, this runner adds following behavior:
- * <ul>
- *   <li>
- *      Initializes mocks annotated with {@link Mock},
- *      so that explicit usage of {@link MockitoAnnotations#initMocks(Object)} is not necessary. 
- *      Mocks are initialized before each test method.
- *   <li>
- *      validates framework usage after each test method. See javadoc for {@link Mockito#validateMockitoUsage()}.
- * </ul>
- * 
- * Runner is completely optional - there are other ways you can get &#064;Mock working, for example by writing a base class.
- * Explicitly validating framework usage is also optional because it is triggered automatically by Mockito every time you use the framework.
- * See javadoc for {@link Mockito#validateMockitoUsage()}.
- * <p>
- * Read more about &#064;Mock annotation in javadoc for {@link MockitoAnnotations}
- * <p>
- * Example:
- * <pre class="code"><code class="java">
- * &#064;RunWith(MockitoJUnitRunner.class)
- * public class ExampleTest {
- * 
- *     &#064;Mock
- *     private List list;
- * 
- *     &#064;Test
- *     public void shouldDoSomething() {
- *         list.add(100);
- *     }
- * }
- * <p>
- * 
- * </code></pre>
- */
-@Deprecated
-public class MockitoJUnit44Runner extends MockitoJUnitRunner {
-
-    public MockitoJUnit44Runner(Class<?> klass) throws InvocationTargetException {
-        super(klass);
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/runners/MockitoJUnitRunner.java b/src/main/java/org/mockito/runners/MockitoJUnitRunner.java
index e065d96..74f025c 100644
--- a/src/main/java/org/mockito/runners/MockitoJUnitRunner.java
+++ b/src/main/java/org/mockito/runners/MockitoJUnitRunner.java
@@ -2,73 +2,65 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.runners;

-

-import org.junit.runner.Description;

-import org.junit.runner.Runner;

-import org.junit.runner.manipulation.Filter;

-import org.junit.runner.manipulation.Filterable;

-import org.junit.runner.manipulation.NoTestsRemainException;

-import org.junit.runner.notification.RunNotifier;

-import org.mockito.Mock;

-import org.mockito.Mockito;

-import org.mockito.MockitoAnnotations;

-import org.mockito.internal.runners.RunnerFactory;

-import org.mockito.internal.runners.RunnerImpl;

-

-import java.lang.reflect.InvocationTargetException;

-

-

-/**

- * Compatible with <b>JUnit 4.4 and higher</b>, this runner adds following behavior:

- * <ul>

- *   <li>

- *      Initializes mocks annotated with {@link Mock},

- *      so that explicit usage of {@link MockitoAnnotations#initMocks(Object)} is not necessary. 

- *      Mocks are initialized before each test method.

- *   <li>

- *      validates framework usage after each test method. See javadoc for {@link Mockito#validateMockitoUsage()}.

- * </ul>

- * 

- * Runner is completely optional - there are other ways you can get &#064;Mock working, for example by writing a base class.

- * Explicitly validating framework usage is also optional because it is triggered automatically by Mockito every time you use the framework.

- * See javadoc for {@link Mockito#validateMockitoUsage()}.

- * <p>

- * Read more about &#064;Mock annotation in javadoc for {@link MockitoAnnotations}

- * <pre class="code"><code class="java">

- * <b>&#064;RunWith(MockitoJUnitRunner.class)</b>

- * public class ExampleTest {

- * 

- *     &#064;Mock

- *     private List list;

- * 

- *     &#064;Test

- *     public void shouldDoSomething() {

- *         list.add(100);

- *     }

- * }

- * </code></pre>

- */

-public class MockitoJUnitRunner extends Runner implements Filterable {

-

-    private final RunnerImpl runner;

-

-    public MockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {

-        runner = new RunnerFactory().create(klass);

-    }

-

-    @Override

-    public void run(final RunNotifier notifier) {           

-        runner.run(notifier);

-    }

-

-    @Override

-    public Description getDescription() {

-        return runner.getDescription();

-    }

-

-	public void filter(Filter filter) throws NoTestsRemainException {

-        //filter is required because without it UnrootedTests show up in Eclipse

-		runner.filter(filter);

-	}

-}
\ No newline at end of file
+package org.mockito.runners;
+
+import java.lang.reflect.InvocationTargetException;
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+
+
+/**
+ * Runner moved to a new place see {@link org.mockito.junit.MockitoJUnitRunner}
+ *
+ * @deprecated Moved to {@link org.mockito.junit.MockitoJUnitRunner}, this class will be removed with Mockito 3
+ */
+@Deprecated
+public class MockitoJUnitRunner extends org.mockito.junit.MockitoJUnitRunner {
+
+    /**
+     * Silent runner moved to a new place see {@link org.mockito.junit.MockitoJUnitRunner.Silent}
+     *
+     * @deprecated Moved to {@link org.mockito.junit.MockitoJUnitRunner.Silent}, this class will be removed with Mockito 3
+     */
+    @Deprecated
+    public static class Silent extends MockitoJUnitRunner {
+        public Silent(Class<?> klass) throws InvocationTargetException {
+            super(klass);
+        }
+    }
+
+    /**
+     * Silent runner moved to a new place see {@link org.mockito.junit.MockitoJUnitRunner.Strict}
+     *
+     * @deprecated Moved to {@link org.mockito.junit.MockitoJUnitRunner.Strict}, this class will be removed with Mockito 3
+     */
+    @Deprecated
+    public static class Strict extends MockitoJUnitRunner {
+        public Strict(Class<?> klass) throws InvocationTargetException {
+            super(klass);
+        }
+    }
+
+    public MockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+        super(klass);
+    }
+
+    @Deprecated
+    @Override
+    public void run(final RunNotifier notifier) {
+        super.run(notifier);
+    }
+
+    @Deprecated
+    @Override
+    public Description getDescription() {
+        return super.getDescription();
+    }
+
+    @Deprecated
+    public void filter(Filter filter) throws NoTestsRemainException {
+        super.filter(filter);
+    }
+}
diff --git a/src/main/java/org/mockito/runners/VerboseMockitoJUnitRunner.java b/src/main/java/org/mockito/runners/VerboseMockitoJUnitRunner.java
index a0f71c9..b86a891 100644
--- a/src/main/java/org/mockito/runners/VerboseMockitoJUnitRunner.java
+++ b/src/main/java/org/mockito/runners/VerboseMockitoJUnitRunner.java
@@ -1,84 +1,75 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.runners;

-

-import org.junit.runner.Description;

-import org.junit.runner.Runner;

-import org.junit.runner.manipulation.Filter;

-import org.junit.runner.manipulation.Filterable;

-import org.junit.runner.manipulation.NoTestsRemainException;

-import org.junit.runner.notification.Failure;

-import org.junit.runner.notification.RunListener;

-import org.junit.runner.notification.RunNotifier;

-import org.mockito.internal.debugging.WarningsCollector;

-import org.mockito.internal.runners.RunnerFactory;

-import org.mockito.internal.runners.RunnerImpl;

-import org.mockito.internal.util.junit.JUnitFailureHacker;

-

-import java.lang.reflect.InvocationTargetException;

-

-/**

- * Experimental implementation that suppose to improve tdd/testing experience. 

- * Don't hesitate to send feedback to mockito@googlegroups.com

- * <b>It is very likely it will change in the next version!</b>

- * <p>

- * This runner does exactly what {@link MockitoJUnitRunner} does but also  

- * adds extra Mocktio hints to the exception message. 

- * The point is that Mockito should help the tdd developer to quickly figure out if the test fails for the right reason and track the reason. 

- * <p>

- * The implementation is pretty hacky - it uses brute force of reflection to modify the exception message and add extra mockito hints.

- * You've been warned. 

- * <p>

- * Do you think it is useful or not? Drop us an email at mockito@googlegroups.com

- * <p>

- * Experimental implementation - will change in future!

- */

-public class VerboseMockitoJUnitRunner extends Runner implements Filterable {

-

-    private final RunnerImpl runner;

-

-    public VerboseMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {

-        this(new RunnerFactory().create(klass));

-    }

-    

-    VerboseMockitoJUnitRunner(RunnerImpl runnerImpl) {

-        this.runner = runnerImpl;

-    }

-    

-    @Override

-    public void run(RunNotifier notifier) {        

-

-        //a listener that changes the failure's exception in a very hacky way...

-        RunListener listener = new RunListener() {

-            

-            WarningsCollector warningsCollector;

-                       

-            @Override

-            public void testStarted(Description description) throws Exception {

-                warningsCollector = new WarningsCollector();

-            }

-            

-            @Override 

-            public void testFailure(final Failure failure) throws Exception {       

-                String warnings = warningsCollector.getWarnings();

-                new JUnitFailureHacker().appendWarnings(failure, warnings);                              

-            }

-        };

-

-        notifier.addFirstListener(listener);

-

-        runner.run(notifier);

-    }

-

-    @Override

-    public Description getDescription() {

-        return runner.getDescription();

-    }

-    

-    public void filter(Filter filter) throws NoTestsRemainException {

-        //filter is required because without it UnrootedTests show up in Eclipse

-        runner.filter(filter);

-    }

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.runners;
+
+import java.lang.reflect.InvocationTargetException;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.internal.debugging.WarningsCollector;
+import org.mockito.internal.junit.util.JUnitFailureHacker;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.InternalRunner;
+
+/**
+ * @deprecated as of 2.1.0. Use the {@link org.mockito.junit.MockitoJUnitRunner} runner instead
+ * which contains support for detecting unused stubs.
+ * <p>
+ * If you still prefer using this runner, tell us why (create ticket in our issue tracker).
+ */
+@Deprecated
+public class VerboseMockitoJUnitRunner extends Runner implements Filterable {
+
+    private final InternalRunner runner;
+
+    public VerboseMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+        this(new RunnerFactory().create(klass));
+    }
+
+    VerboseMockitoJUnitRunner(InternalRunner runner) {
+        this.runner = runner;
+    }
+
+    @Override
+    public void run(RunNotifier notifier) {
+
+        //a listener that changes the failure's exception in a very hacky way...
+        RunListener listener = new RunListener() {
+
+            WarningsCollector warningsCollector;
+
+            @Override
+            public void testStarted(Description description) throws Exception {
+                warningsCollector = new WarningsCollector();
+            }
+
+            @Override
+            @SuppressWarnings("deprecation")
+            public void testFailure(final Failure failure) throws Exception {
+                String warnings = warningsCollector.getWarnings();
+                new JUnitFailureHacker().appendWarnings(failure, warnings);
+            }
+        };
+
+        notifier.addFirstListener(listener);
+
+        runner.run(notifier);
+    }
+
+    @Override
+    public Description getDescription() {
+        return runner.getDescription();
+    }
+
+    public void filter(Filter filter) throws NoTestsRemainException {
+        //filter is required because without it UnrootedTests show up in Eclipse
+        runner.filter(filter);
+    }
+}
diff --git a/src/main/java/org/mockito/runners/package-info.java b/src/main/java/org/mockito/runners/package-info.java
new file mode 100644
index 0000000..ab2fb8c
--- /dev/null
+++ b/src/main/java/org/mockito/runners/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * JUnit runners.
+ */
+@Deprecated
+package org.mockito.runners;
diff --git a/src/main/java/org/mockito/runners/package.html b/src/main/java/org/mockito/runners/package.html
deleted file mode 100644
index 2ce69b8..0000000
--- a/src/main/java/org/mockito/runners/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-JUnit runners.
-</body>
diff --git a/src/main/java/org/mockito/session/MockitoSessionBuilder.java b/src/main/java/org/mockito/session/MockitoSessionBuilder.java
new file mode 100644
index 0000000..c357141
--- /dev/null
+++ b/src/main/java/org/mockito/session/MockitoSessionBuilder.java
@@ -0,0 +1,75 @@
+package org.mockito.session;
+
+import org.mockito.Incubating;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.misusing.UnfinishedMockingSessionException;
+import org.mockito.quality.Strictness;
+
+/**
+ * Fluent builder interface for {@code MockitoSession} objects.
+ * See the documentation and examples in Javadoc for {@link MockitoSession}.
+ *
+ * @since 2.7.0
+ */
+@Incubating
+public interface MockitoSessionBuilder {
+
+    /**
+     * Configures the test class instance for initialization of fields annotated with Mockito annotations
+     * like {@link org.mockito.Mock}.
+     * When this method is invoked it <strong>does not perform</strong> initialization of mocks on the spot!
+     * Only when {@link #startMocking()} is invoked then annotated fields will be initialized.
+     * Traditional API to initialize mocks, the {@link MockitoAnnotations#initMocks(Object)} method
+     * has limited support for driving cleaner tests because it does not support configuring {@link Strictness}.
+     * Want cleaner tests and better productivity?
+     * Migrate from {@link MockitoAnnotations#initMocks(Object)}
+     * to {@link MockitoSession}!
+     * <p>
+     * See code sample in {@link MockitoSession}.
+     *
+     * @param testClassInstance test class instance that contains fields with Mockito annotations to be initialized.
+     *  Passing {@code null} is permitted and will make the session use a default value.
+     *  The current default is '{@code new Object()}'.
+     * @return the same builder instance for fluent configuration of {@code MockitoSession}.
+     * @since 2.7.0
+     */
+    @Incubating
+    MockitoSessionBuilder initMocks(Object testClassInstance);
+
+    /**
+     * Configures strictness of {@code MockitoSession} instance.
+     * See examples in {@link MockitoSession}.
+     *
+     * @param strictness for {@code MockitoSession} instance.
+     *  Passing {@code null} is permitted and will make the session use a default value.
+     *  The current default is {@link Strictness#STRICT_STUBS}.
+     *
+     * @return the same builder instance for fluent configuration of {@code MockitoSession}.
+     * @since 2.7.0
+     */
+    @Incubating
+    MockitoSessionBuilder strictness(Strictness strictness);
+
+    /**
+     * Starts new mocking session! Creates new {@code MockitoSession} instance to initialize the session.
+     * At this point annotated fields are initialized per {@link #initMocks(Object)} method.
+     * When you are done with the session it is required to invoke {@link MockitoSession#finishMocking()}.
+     * This will trigger stubbing validation, cleaning up the internal state like removal of internal listeners.
+     * <p>
+     * Mockito tracks created sessions internally and prevents the user from creating new sessions without
+     * using {@link MockitoSession#finishMocking()}.
+     * When you run tests concurrently in multiple threads, it is legal for each thread to have single active Mockito session.
+     * When you attempt to start new session in a thread that already has an unfinished session
+     * {@link UnfinishedMockingSessionException} will be triggered.
+     * <p>
+     * See examples in {@link MockitoSession}.
+     *
+     * @return new {@code MockitoSession} instance
+     * @since 2.7.0
+     * @throws UnfinishedMockingSessionException
+     *  when previous session was not concluded with {@link MockitoSession#finishMocking()}
+     */
+    @Incubating
+    MockitoSession startMocking() throws UnfinishedMockingSessionException;
+}
diff --git a/src/main/java/org/mockito/stubbing/Answer.java b/src/main/java/org/mockito/stubbing/Answer.java
index 997d69d..ed65ea9 100644
--- a/src/main/java/org/mockito/stubbing/Answer.java
+++ b/src/main/java/org/mockito/stubbing/Answer.java
@@ -2,38 +2,38 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.stubbing;

-

-import org.mockito.invocation.InvocationOnMock;

-

-/**

- * Generic interface to be used for configuring mock's answer. 

- * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.   

- * <p>

- * Example of stubbing a mock with custom answer: 

- * 

- * <pre class="code"><code class="java">

- * when(mock.someMethod(anyString())).thenAnswer(new Answer() {

- *     Object answer(InvocationOnMock invocation) {

- *         Object[] args = invocation.getArguments();

- *         Object mock = invocation.getMock();

- *         return "called with arguments: " + Arrays.toString(args);

- *     }

- * });

- * 

- * //Following prints "called with arguments: [foo]"

- * System.out.println(mock.someMethod("foo"));

- * </code></pre>

- * 

- * @param <T> the type to return.

- */

-public interface Answer<T> {

-    /**

-     * @param invocation the invocation on the mock.

-     *

-     * @return the value to be returned

-     *

-     * @throws Throwable the throwable to be thrown

-     */

-    T answer(InvocationOnMock invocation) throws Throwable;

-}
\ No newline at end of file
+package org.mockito.stubbing;
+
+import org.mockito.invocation.InvocationOnMock;
+
+/**
+ * Generic interface to be used for configuring mock's answer.
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer() {
+ *     Object answer(InvocationOnMock invocation) {
+ *         Object[] args = invocation.getArguments();
+ *         Object mock = invocation.getMock();
+ *         return "called with arguments: " + Arrays.toString(args);
+ *     }
+ * });
+ *
+ * //Following prints "called with arguments: [foo]"
+ * System.out.println(mock.someMethod("foo"));
+ * </code></pre>
+ *
+ * @param <T> the type to return.
+ */
+public interface Answer<T> {
+    /**
+     * @param invocation the invocation on the mock.
+     *
+     * @return the value to be returned
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(InvocationOnMock invocation) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/Answer1.java b/src/main/java/org/mockito/stubbing/Answer1.java
new file mode 100644
index 0000000..75e0923
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/Answer1.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a single argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer&lt;Integer, String&gt;() {
+ *     Integer answer(String arg) {
+ *         return arg.length();
+ *     }
+ * });
+ *
+ * //Following will print "3"
+ * System.out.println(mock.someMethod("foo"));
+ * </code></pre>
+ *
+ * @param <T> return type
+ * @param <A0> type of the single argument
+ * @see Answer
+ */
+@Incubating
+public interface Answer1<T, A0> {
+    /**
+     * @param argument0 the single argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0) throws Throwable;
+}
+
diff --git a/src/main/java/org/mockito/stubbing/Answer2.java b/src/main/java/org/mockito/stubbing/Answer2.java
new file mode 100644
index 0000000..b28fa0b
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/Answer2.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a two argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyChar())).thenAnswer(new Answer&lt;String, String, Character&gt;() {
+ *     String answer(String s, Character c) {
+ *         return s.replace('f', c);
+ *     }
+ * });
+ *
+ * //Following will print "bar"
+ * System.out.println(mock.someMethod("far", 'b'));
+ * </code></pre>
+ *
+ * @param <T> return type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @see Answer
+ */
+@Incubating
+public interface Answer2<T, A0, A1> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/Answer3.java b/src/main/java/org/mockito/stubbing/Answer3.java
new file mode 100644
index 0000000..bc9a365
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/Answer3.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a three argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyInt(), anyString(), anyChar())).thenAnswer(
+ *     new Answer&lt;StringBuilder, Integer, String, Character&gt;() {
+ *         StringBuilder answer(Integer i, String s, Character c) {
+ *             return new StringBuilder().append(i).append(s).append(c);
+ *         }
+ *     });
+ *
+ * //Following will print "3xyz"
+ * System.out.println(mock.someMethod(3, "xy", 'z'));
+ * </code></pre>
+ *
+ * @param <T> return type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @see Answer
+ */
+@Incubating
+public interface Answer3<T, A0, A1, A2> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1, A2 argument2) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/Answer4.java b/src/main/java/org/mockito/stubbing/Answer4.java
new file mode 100644
index 0000000..8d26784
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/Answer4.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a four argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyInt(), anyString(), anyChar(), any())).thenAnswer(
+ *     new Answer&lt;StringBuilder, Integer, String, Character, Object&gt;() {
+ *         StringBuilder answer(Integer i, String s, Character c, Object o) {
+ *             return new StringBuilder().append(i).append(s).append(c).append(o.hashCode());
+ *         }
+ *     });
+ *
+ * //Following will print a string like "3xyz131635550"
+ * System.out.println(mock.someMethod(3, "xy", 'z', new Object()));
+ * </code></pre>
+ *
+ * @param <T> return type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @see Answer
+ */
+@Incubating
+public interface Answer4<T, A0, A1, A2, A3> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/Answer5.java b/src/main/java/org/mockito/stubbing/Answer5.java
new file mode 100644
index 0000000..30d50f9
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/Answer5.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a five argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyInt(), anyString(), anyChar(), any(), anyBoolean())).thenAnswer(
+ *     new Answer&lt;StringBuilder, Integer, String, Character, Object, Boolean&gt;() {
+ *         StringBuilder answer(Integer i, String s, Character c, Object o, Boolean isIt) {
+ *             return new StringBuilder().append(i).append(s).append(c).append(o.hashCode()).append(isIt);
+ *         }
+ *     });
+ *
+ * //Following will print a string like "3xyz131635550true"
+ * System.out.println(mock.someMethod(3, "xy", 'z', new Object(), true));
+ * </code></pre>
+ *
+ * @param <T> return type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @see Answer
+ */
+@Incubating
+public interface Answer5<T, A0, A1, A2, A3, A4> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     * @param argument4 the fifth argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3, A4 argument4) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/DeprecatedOngoingStubbing.java b/src/main/java/org/mockito/stubbing/DeprecatedOngoingStubbing.java
deleted file mode 100644
index d41137f..0000000
--- a/src/main/java/org/mockito/stubbing/DeprecatedOngoingStubbing.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.stubbing;

-

-import org.mockito.Mockito;

-import org.mockito.internal.progress.IOngoingStubbing;

-

-/**

- * Stubs a method call with return value or an exception. E.g:

- *

- * <pre class="code"><code class="java">

- * stub(mock.someMethod()).toReturn(10);

- *

- * //you can use flexible argument matchers, e.g:

- * stub(mock.someMethod(<b>anyString()</b>)).toReturn(10);

- *

- * //setting exception to be thrown:

- * stub(mock.someMethod("some arg")).toThrow(new RuntimeException());

- *

- * //you can stub with different behavior for consecutive method calls.

- * //Last stubbing (e.g: toReturn("foo")) determines the behavior for further consecutive calls.

- * stub(mock.someMethod("some arg"))

- *  .toThrow(new RuntimeException())

- *  .toReturn("foo");

- *

- * </code></pre>

- *

- * See examples in javadoc for {@link Mockito#stub}

- */

-public interface DeprecatedOngoingStubbing<T> extends IOngoingStubbing {

-

-    /**

-     * Set a return value for the stubbed method. E.g:

-     * <pre class="code"><code class="java">

-     * stub(mock.someMethod()).toReturn(10);

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito#stub}

-     *

-     * @param value return value

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    DeprecatedOngoingStubbing<T> toReturn(T value);

-

-    /**

-     * Set a Throwable to be thrown when the stubbed method is called. E.g:

-     * <pre class="code"><code class="java">

-     * stub(mock.someMethod()).toThrow(new RuntimeException());

-     * </code></pre>

-     *

-     * If throwable is a checked exception then it has to

-     * match one of the checked exceptions of method signature.

-     *

-     * See examples in javadoc for {@link Mockito#stub}

-     *

-     * @param throwable to be thrown on method invocation

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    DeprecatedOngoingStubbing<T> toThrow(Throwable throwable);

-

-    /**

-     * Set a generic Answer for the stubbed method. E.g:

-     * <pre class="code"><code class="java">

-     * stub(mock.someMethod(10)).toAnswer(new Answer&lt;Integer&gt;() {

-     *     public Integer answer(InvocationOnMock invocation) throws Throwable {

-     *         return (Integer) invocation.getArguments()[0];

-     *     }

-     * }

-     * </code></pre>

-     *

-     * @param answer the custom answer to execute.

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    DeprecatedOngoingStubbing<T> toAnswer(Answer<?> answer);

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/stubbing/OngoingStubbing.java b/src/main/java/org/mockito/stubbing/OngoingStubbing.java
index c60f724..bc768d2 100644
--- a/src/main/java/org/mockito/stubbing/OngoingStubbing.java
+++ b/src/main/java/org/mockito/stubbing/OngoingStubbing.java
@@ -2,202 +2,237 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.stubbing;

-

-import org.mockito.Mockito;

-import org.mockito.internal.progress.IOngoingStubbing;

-

-/**

- * Simply put: "<b>When</b> the x method is called <b>then</b> return y". E.g:

- *

- * <pre class="code"><code class="java">

- * <b>when</b>(mock.someMethod()).<b>thenReturn</b>(10);

- *

- * //you can use flexible argument matchers, e.g:

- * when(mock.someMethod(<b>anyString()</b>)).thenReturn(10);

- *

- * //setting exception to be thrown:

- * when(mock.someMethod("some arg")).thenThrow(new RuntimeException());

- *

- * //you can set different behavior for consecutive method calls.

- * //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.

- * when(mock.someMethod("some arg"))

- *  .thenThrow(new RuntimeException())

- *  .thenReturn("foo");

- * 

- * //There is a shorter way of consecutive stubbing:

- * when(mock.someMethod()).thenReturn(1,2,3);

- * when(mock.otherMethod()).thenThrow(exc1, exc2);

- * </code></pre>

- *

- * See examples in javadoc for {@link Mockito#when}

- */

-public interface OngoingStubbing<T> extends IOngoingStubbing {

-

-    /**

-     * Sets a return value to be returned when the method is called. E.g:

-     * <pre class="code"><code class="java">

-     * when(mock.someMethod()).thenReturn(10);

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito#when}

-     *

-     * @param value return value

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    OngoingStubbing<T> thenReturn(T value);

-

-    /**

-     * Sets consecutive return values to be returned when the method is called. E.g:

-     * <pre class="code"><code class="java">

-     * when(mock.someMethod()).thenReturn(1, 2, 3);

-     * </code></pre>

-     *

-     * Last return value in the sequence (in example: 3) determines the behavior of further consecutive calls.

-     * <p>

-     * See examples in javadoc for {@link Mockito#when}

-     *

-     * @param value first return value

-     * @param values next return values

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    OngoingStubbing<T> thenReturn(T value, T... values);

-

-    /**

-     * Sets Throwable objects to be thrown when the method is called. E.g:

-     * <pre class="code"><code class="java">

-     * when(mock.someMethod()).thenThrow(new RuntimeException());

-     * </code></pre>

-     *

-     * If throwables contain a checked exception then it has to

-     * match one of the checked exceptions of method signature.

-     * <p>

-     * You can specify throwables to be thrown for consecutive calls. 

-     * In that case the last throwable determines the behavior of further consecutive calls.

-     * <p>

-     * if throwable is null then exception will be thrown.

-     * <p>

-     * See examples in javadoc for {@link Mockito#when}

-     *

-     * @param throwables to be thrown on method invocation

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    OngoingStubbing<T> thenThrow(Throwable... throwables);

-

-    /**

-     * Sets Throwable classes to be thrown when the method is called. E.g:

-     * <pre class="code"><code class="java">

-     * when(mock.someMethod()).thenThrow(RuntimeException.class);

-     * </code></pre>

-     *

-     * <p>

-     * Each throwable class will be instantiated for each method invocation.

-     * <p>

-     * If throwableClasses contain a checked exception then it has to

-     * match one of the checked exceptions of method signature.

-     * <p>

-     * You can specify throwableClasses to be thrown for consecutive calls.

-     * In that case the last throwable determines the behavior of further consecutive calls.

-     * <p>

-     * if throwable is null then exception will be thrown.

-     * <p>

-     * See examples in javadoc for {@link Mockito#when}

-     *

-     * @param throwableClasses to be thrown on method invocation

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     * @since 1.9.0

-     */

-    OngoingStubbing<T> thenThrow(Class<? extends Throwable>... throwableClasses);

-

-    /**     

-     * Sets the real implementation to be called when the method is called on a mock object.

-     * <p>

-     * As usual you are going to read <b>the partial mock warning</b>:

-     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.

-     * How does partial mock fit into this paradigm? Well, it just doesn't... 

-     * Partial mock usually means that the complexity has been moved to a different method on the same object.

-     * In most cases, this is not the way you want to design your application.

-     * <p>

-     * However, there are rare cases when partial mocks come handy: 

-     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)

-     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.

-     * <pre class="code"><code class="java">

-     *   // someMethod() must be safe (e.g. doesn't throw, doesn't have dependencies to the object state, etc.)

-     *   // if it isn't safe then you will have trouble stubbing it using this api. Use Mockito.doCallRealMethod() instead. 

-     *   when(mock.someMethod()).thenCallRealMethod();

-     *   

-     *   // calls real method:

-     *   mock.someMethod();

-     *   

-     * </code></pre>

-     * See also javadoc {@link Mockito#spy(Object)} to find out more about partial mocks. 

-     * <b>Mockito.spy() is a recommended way of creating partial mocks.</b> 

-     * The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.

-     * <p>

-     * See examples in javadoc for {@link Mockito#when}

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    OngoingStubbing<T> thenCallRealMethod();

-

-    /**

-     * Sets a generic Answer for the method. E.g:

-     * <pre class="code"><code class="java">

-     * when(mock.someMethod(10)).thenAnswer(new Answer&lt;Integer&gt;() {

-     *     public Integer answer(InvocationOnMock invocation) throws Throwable {

-     *         return (Integer) invocation.getArguments()[0];

-     *     }

-     * }

-     * </code></pre>

-     *

-     * @param answer the custom answer to execute.

-     *

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     */

-    OngoingStubbing<T> thenAnswer(Answer<?> answer);

-

-    /**

-     * Sets a generic Answer for the method.

-     *

-     * This method is an alias of {@link #thenAnswer(Answer)}. This alias allows

-     * more readable tests on occasion, for example:

-     * <pre class="code"><code class="java">

-     * //using 'then' alias:

-     * when(mock.foo()).then(returnCoolValue());

-     *

-     * //versus good old 'thenAnswer:

-     * when(mock.foo()).thenAnswer(byReturningCoolValue());

-     * </code></pre>

-     *

-     * @param answer the custom answer to execute.

-     * @return iOngoingStubbing object that allows stubbing consecutive calls

-     *

-     * @see #thenAnswer(Answer)

-     * @since 1.9.0

-     */

-    OngoingStubbing<T> then(Answer<?> answer);

-

-    /**

-     * Returns the mock that was used for this stub.

-     * <p>

-     * It allows to create a stub in one line of code.

-     * This can be helpful to keep test code clean.

-     * For example, some boring stub can be created & stubbed at field initialization in a test:

-     * <pre class="code"><code class="java">

-     * public class CarTest {

-     *   Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();

-     *

-     *   &#064;Test public void should... {}

-     * </code></pre>

-     *

-     * @param <M> The mock type given by the variable type.

-     * @return Mock used in this ongoing stubbing.

-     * @since 1.9.0

-     */

-    <M> M getMock();

-

-}

+package org.mockito.stubbing;
+
+import org.mockito.Mockito;
+
+/**
+ * Simply put: "<b>When</b> the x method is called <b>then</b> return y". E.g:
+ *
+ * <pre class="code"><code class="java">
+ * <b>when</b>(mock.someMethod()).<b>thenReturn</b>(10);
+ *
+ * //you can use flexible argument matchers, e.g:
+ * when(mock.someMethod(<b>anyString()</b>)).thenReturn(10);
+ *
+ * //setting exception to be thrown:
+ * when(mock.someMethod("some arg")).thenThrow(new RuntimeException());
+ *
+ * //you can set different behavior for consecutive method calls.
+ * //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.
+ * when(mock.someMethod("some arg"))
+ *  .thenThrow(new RuntimeException())
+ *  .thenReturn("foo");
+ *
+ * //There is a shorter way of consecutive stubbing:
+ * when(mock.someMethod()).thenReturn(1,2,3);
+ * when(mock.otherMethod()).thenThrow(exc1, exc2);
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#when}
+ */
+public interface OngoingStubbing<T> {
+
+    /**
+     * Sets a return value to be returned when the method is called. E.g:
+     * <pre class="code"><code class="java">
+     * when(mock.someMethod()).thenReturn(10);
+     * </code></pre>
+     *
+     * See examples in javadoc for {@link Mockito#when}
+     *
+     * @param value return value
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     */
+    OngoingStubbing<T> thenReturn(T value);
+
+    /**
+     * Sets consecutive return values to be returned when the method is called. E.g:
+     * <pre class="code"><code class="java">
+     * when(mock.someMethod()).thenReturn(1, 2, 3);
+     * </code></pre>
+     *
+     * Last return value in the sequence (in example: 3) determines the behavior of further consecutive calls.
+     * <p>
+     * See examples in javadoc for {@link Mockito#when}
+     *
+     * @param value first return value
+     * @param values next return values
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     */
+    // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation warnings (on call site)
+    @SuppressWarnings ({"unchecked", "varargs"})
+    OngoingStubbing<T> thenReturn(T value, T... values);
+
+    /**
+     * Sets Throwable objects to be thrown when the method is called. E.g:
+     * <pre class="code"><code class="java">
+     * when(mock.someMethod()).thenThrow(new RuntimeException());
+     * </code></pre>
+     *
+     * If throwables contain a checked exception then it has to
+     * match one of the checked exceptions of method signature.
+     * <p>
+     * You can specify throwables to be thrown for consecutive calls.
+     * In that case the last throwable determines the behavior of further consecutive calls.
+     * <p>
+     * If throwable is null then exception will be thrown.
+     * <p>
+     * See examples in javadoc for {@link Mockito#when}
+     *
+     * @param throwables to be thrown on method invocation
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     */
+    OngoingStubbing<T> thenThrow(Throwable... throwables);
+
+    /**
+     * Sets a Throwable type to be thrown when the method is called. E.g:
+     * <pre class="code"><code class="java">
+     * when(mock.someMethod()).thenThrow(RuntimeException.class);
+     * </code></pre>
+     *
+     * <p>
+     * If the throwable class is a checked exception then it has to
+     * match one of the checked exceptions of the stubbed method signature.
+     * <p>
+     * If throwable is null then exception will be thrown.
+     * <p>
+     * See examples in javadoc for {@link Mockito#when}
+     *
+     * <p>Note depending on the JVM, stack trace information may not be available in
+     * the generated throwable instance.  If you require stack trace information,
+     * use {@link OngoingStubbing#thenThrow(Throwable...)} instead.
+     *
+     * @param throwableType to be thrown on method invocation
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     * @since 2.1.0
+     */
+    OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableType);
+
+    /**
+     * Sets Throwable classes to be thrown when the method is called. E.g:
+     * <pre class="code"><code class="java">
+     * when(mock.someMethod()).thenThrow(RuntimeException.class);
+     * </code></pre>
+     *
+     * <p>
+     * Each throwable class will be instantiated for each method invocation.
+     * <p>
+     * If <code>throwableTypes</code> contain a checked exception then it has to
+     * match one of the checked exceptions of method signature.
+     * <p>
+     * You can specify <code>throwableTypes</code> to be thrown for consecutive calls.
+     * In that case the last throwable determines the behavior of further consecutive calls.
+     * <p>
+     * If throwable is null then exception will be thrown.
+     * <p>
+     * See examples in javadoc for {@link Mockito#when}
+     *
+     * <p>Note since JDK 7, invoking this method will raise a compiler warning "possible heap pollution",
+     * this API is safe to use. If you don't want to see this warning it is possible to chain {@link #thenThrow(Class)}
+     * <p>Note depending on the JVM, stack trace information may not be available in
+     * the generated throwable instance.  If you require stack trace information,
+     * use {@link OngoingStubbing#thenThrow(Throwable...)} instead.
+     *
+     * @param toBeThrown to be thrown on method invocation
+     * @param nextToBeThrown next to be thrown on method invocation
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     * @since 2.1.0
+     */
+    // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation warnings (on call site)
+    @SuppressWarnings ({"unchecked", "varargs"})
+    OngoingStubbing<T> thenThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown);
+
+    /**
+     * Sets the real implementation to be called when the method is called on a mock object.
+     * <p>
+     * As usual you are going to read <b>the partial mock warning</b>:
+     * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+     * How does partial mock fit into this paradigm? Well, it just doesn't...
+     * Partial mock usually means that the complexity has been moved to a different method on the same object.
+     * In most cases, this is not the way you want to design your application.
+     * <p>
+     * However, there are rare cases when partial mocks come handy:
+     * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+     * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+     * <pre class="code"><code class="java">
+     *   // someMethod() must be safe (e.g. doesn't throw, doesn't have dependencies to the object state, etc.)
+     *   // if it isn't safe then you will have trouble stubbing it using this api. Use Mockito.doCallRealMethod() instead.
+     *   when(mock.someMethod()).thenCallRealMethod();
+     *
+     *   // calls real method:
+     *   mock.someMethod();
+     *
+     * </code></pre>
+     * See also javadoc {@link Mockito#spy(Object)} to find out more about partial mocks.
+     * <b>Mockito.spy() is a recommended way of creating partial mocks.</b>
+     * The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.
+     * <p>
+     * See examples in javadoc for {@link Mockito#when}
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     */
+    OngoingStubbing<T> thenCallRealMethod();
+
+    /**
+     * Sets a generic Answer for the method. E.g:
+     * <pre class="code"><code class="java">
+     * when(mock.someMethod(10)).thenAnswer(new Answer&lt;Integer&gt;() {
+     *     public Integer answer(InvocationOnMock invocation) throws Throwable {
+     *         return (Integer) invocation.getArguments()[0];
+     *     }
+     * }
+     * </code></pre>
+     *
+     * @param answer the custom answer to execute.
+     *
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     */
+    OngoingStubbing<T> thenAnswer(Answer<?> answer);
+
+    /**
+     * Sets a generic Answer for the method.
+     *
+     * This method is an alias of {@link #thenAnswer(Answer)}. This alias allows
+     * more readable tests on occasion, for example:
+     * <pre class="code"><code class="java">
+     * //using 'then' alias:
+     * when(mock.foo()).then(returnCoolValue());
+     *
+     * //versus good old 'thenAnswer:
+     * when(mock.foo()).thenAnswer(byReturningCoolValue());
+     * </code></pre>
+     *
+     * @param answer the custom answer to execute.
+     * @return iOngoingStubbing object that allows stubbing consecutive calls
+     *
+     * @see #thenAnswer(Answer)
+     * @since 1.9.0
+     */
+    OngoingStubbing<T> then(Answer<?> answer);
+
+    /**
+     * Returns the mock that was used for this stub.
+     * <p>
+     * It allows to create a stub in one line of code.
+     * This can be helpful to keep test code clean.
+     * For example, some boring stub can be created & stubbed at field initialization in a test:
+     * <pre class="code"><code class="java">
+     * public class CarTest {
+     *   Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();
+     *
+     *   &#064;Test public void should... {}
+     * </code></pre>
+     *
+     * @param <M> The mock type given by the variable type.
+     * @return Mock used in this ongoing stubbing.
+     * @since 1.9.0
+     */
+    <M> M getMock();
+
+}
diff --git a/src/main/java/org/mockito/stubbing/Stubber.java b/src/main/java/org/mockito/stubbing/Stubber.java
index 9775628..b7507a7 100644
--- a/src/main/java/org/mockito/stubbing/Stubber.java
+++ b/src/main/java/org/mockito/stubbing/Stubber.java
@@ -2,146 +2,179 @@
  * Copyright (c) 2007 Mockito contributors
  * This program is made available under the terms of the MIT License.
  */
-package org.mockito.stubbing;

-

-import org.mockito.Mockito;

-

-/**

- * Allows to choose a method when stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style

- * <p> 

- * Example:

- * <pre class="code"><code class="java">

- *   doThrow(new RuntimeException()).when(mockedList).clear();

- *   

- *   //following throws RuntimeException:

- *   mockedList.clear();

- * </code></pre>

- * 

- * Also useful when stubbing consecutive calls:

- * 

- * <pre class="code"><code class="java">

- *   doThrow(new RuntimeException("one")).

- *   doThrow(new RuntimeException("two"))

- *   .when(mock).someVoidMethod();

- * </code></pre>

- * 

- * Read more about those methods:

- * <p>

- * {@link Mockito#doThrow(Throwable)}

- * <p>

- * {@link Mockito#doAnswer(Answer)}

- * <p>

- * {@link Mockito#doNothing()}

- * <p>

- * {@link Mockito#doReturn(Object)}

- * <p>

- * 

- * See examples in javadoc for {@link Mockito}

- */

-@SuppressWarnings("unchecked")

-public interface Stubber {

-

-    /**

-     * Allows to choose a method when stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style

-     * <p> 

-     * Example:

-     * <pre class="code"><code class="java">

-     *   doThrow(new RuntimeException())

-     *   .when(mockedList).clear();

-     *   

-     *   //following throws RuntimeException:

-     *   mockedList.clear();

-     * </code></pre>

-     * 

-     * Read more about those methods:

-     * <p>

-     * {@link Mockito#doThrow(Throwable)}

-     * <p>

-     * {@link Mockito#doAnswer(Answer)}

-     * <p>

-     * {@link Mockito#doNothing()}

-     * <p>

-     * {@link Mockito#doReturn(Object)}

-     * <p>

-     * 

-     *  See examples in javadoc for {@link Mockito}

-     * 

-     * @param mock The mock

-     * @return select method for stubbing

-     */

-    <T> T when(T mock);

-

-    /**

-     * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Throwable)} style:

-     * <pre class="code"><code class="java">

-     *   doThrow(new RuntimeException("one")).

-     *   doThrow(new RuntimeException("two"))

-     *   .when(mock).someVoidMethod();

-     * </code></pre>

-     * See javadoc for {@link Mockito#doThrow(Throwable)}

-     * 

-     * @param toBeThrown to be thrown when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    Stubber doThrow(Throwable toBeThrown);

-

-    /**

-     * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Class)} style:

-     * <pre class="code"><code class="java">

-     *   doThrow(RuntimeException.class).

-     *   doThrow(IllegalArgumentException.class)

-     *   .when(mock).someVoidMethod();

-     * </code></pre>

-     * See javadoc for {@link Mockito#doThrow(Class)}

-     *

-     * @param toBeThrown exception class to be thrown when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    Stubber doThrow(Class<? extends Throwable> toBeThrown);

-

-    /**

-     * Use it for stubbing consecutive calls in {@link Mockito#doAnswer(Answer)} style:

-     * <pre class="code"><code class="java">

-     *   doAnswer(answerOne).

-     *   doAnswer(answerTwo)

-     *   .when(mock).someVoidMethod();

-     * </code></pre>

-     * See javadoc for {@link Mockito#doAnswer(Answer)}

-     * 

-     * @param answer to answer when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    Stubber doAnswer(Answer answer);    

-    

-    /**

-     * Use it for stubbing consecutive calls in {@link Mockito#doNothing()} style:

-     * <pre class="code"><code class="java">

-     *   doNothing().

-     *   doThrow(new RuntimeException("two"))

-     *   .when(mock).someVoidMethod();

-     * </code></pre>

-     * See javadoc for {@link Mockito#doNothing()}

-     * 

-     * @return stubber - to select a method for stubbing

-     */

-    Stubber doNothing();

-    

-    /**

-     * Use it for stubbing consecutive calls in {@link Mockito#doReturn(Object)} style.

-     * <p>

-     * See javadoc for {@link Mockito#doReturn(Object)}

-     * 

-     * @param toBeReturned to be returned when the stubbed method is called

-     * @return stubber - to select a method for stubbing

-     */

-    Stubber doReturn(Object toBeReturned);

-

-    /**

-     * Use it for stubbing consecutive calls in {@link Mockito#doCallRealMethod()} style.

-     * <p>

-     * See javadoc for {@link Mockito#doCallRealMethod()}

-     *

-     * @return stubber - to select a method for stubbing

-     */

-    Stubber doCallRealMethod();

-}

+package org.mockito.stubbing;
+
+import org.mockito.Mockito;
+
+/**
+ * Allows to choose a method when stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ *   doThrow(new RuntimeException()).when(mockedList).clear();
+ *
+ *   //following throws RuntimeException:
+ *   mockedList.clear();
+ * </code></pre>
+ *
+ * Also useful when stubbing consecutive calls:
+ *
+ * <pre class="code"><code class="java">
+ *   doThrow(new RuntimeException("one")).
+ *   doThrow(new RuntimeException("two"))
+ *   .when(mock).someVoidMethod();
+ * </code></pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable[])}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+@SuppressWarnings("unchecked")
+public interface Stubber {
+
+    /**
+     * Allows to choose a method when stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style
+     * <p>
+     * Example:
+     * <pre class="code"><code class="java">
+     *   doThrow(new RuntimeException())
+     *   .when(mockedList).clear();
+     *
+     *   //following throws RuntimeException:
+     *   mockedList.clear();
+     * </code></pre>
+     *
+     * Read more about those methods:
+     * <p>
+     * {@link Mockito#doThrow(Throwable[])}
+     * <p>
+     * {@link Mockito#doAnswer(Answer)}
+     * <p>
+     * {@link Mockito#doNothing()}
+     * <p>
+     * {@link Mockito#doReturn(Object)}
+     * <p>
+     *
+     * See examples in javadoc for {@link Mockito}
+     *
+     * @param mock The mock
+     * @return select method for stubbing
+     */
+    <T> T when(T mock);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Throwable[])} style:
+     * <pre class="code"><code class="java">
+     *   doThrow(new RuntimeException("one")).
+     *   doThrow(new RuntimeException("two"))
+     *       .when(mock).someVoidMethod();
+     * </code></pre>
+     * See javadoc for {@link Mockito#doThrow(Throwable[])}
+     *
+     * @param toBeThrown to be thrown when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    Stubber doThrow(Throwable... toBeThrown);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Class)} style:
+     * <pre class="code"><code class="java">
+     *   doThrow(RuntimeException.class).
+     *   doThrow(IllegalArgumentException.class)
+     *       .when(mock).someVoidMethod();
+     * </code></pre>
+     * See javadoc for {@link Mockito#doThrow(Class)}
+     *
+     * @param toBeThrown exception class to be thrown when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     *
+     * @since 2.1.0
+     */
+    Stubber doThrow(Class<? extends Throwable> toBeThrown);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Class)} style:
+     * <pre class="code"><code class="java">
+     *   doThrow(RuntimeException.class).
+     *   doThrow(IllegalArgumentException.class)
+     *       .when(mock).someVoidMethod();
+     * </code></pre>
+     * See javadoc for {@link Mockito#doThrow(Class)}
+     *
+     * @param toBeThrown exception class to be thrown when the stubbed method is called
+     * @param nextToBeThrown exception class next to be thrown when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     *
+     * @since 2.1.0
+     */
+    // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation
+    @SuppressWarnings ({"unchecked", "varargs"})
+    Stubber doThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doAnswer(Answer)} style:
+     * <pre class="code"><code class="java">
+     *   doAnswer(answerOne).
+     *   doAnswer(answerTwo)
+     *       .when(mock).someVoidMethod();
+     * </code></pre>
+     * See javadoc for {@link Mockito#doAnswer(Answer)}
+     *
+     * @param answer to answer when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    Stubber doAnswer(Answer answer);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doNothing()} style:
+     * <pre class="code"><code class="java">
+     *   doNothing().
+     *   doThrow(new RuntimeException("two"))
+     *       .when(mock).someVoidMethod();
+     * </code></pre>
+     * See javadoc for {@link Mockito#doNothing()}
+     *
+     * @return stubber - to select a method for stubbing
+     */
+    Stubber doNothing();
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doReturn(Object)} style.
+     * <p>
+     * See javadoc for {@link Mockito#doReturn(Object)}
+     *
+     * @param toBeReturned to be returned when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    Stubber doReturn(Object toBeReturned);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doReturn(Object)} style.
+     * <p>
+     * See javadoc for {@link Mockito#doReturn(Object, Object...)}
+     *
+     * @param toBeReturned to be returned when the stubbed method is called
+     * @param nextToBeReturned to be returned in consecutive calls when the stubbed method is called
+     * @return stubber - to select a method for stubbing
+     */
+    @SuppressWarnings({"unchecked", "varargs"})
+    Stubber doReturn(Object toBeReturned, Object... nextToBeReturned);
+
+    /**
+     * Use it for stubbing consecutive calls in {@link Mockito#doCallRealMethod()} style.
+     * <p>
+     * See javadoc for {@link Mockito#doCallRealMethod()}
+     *
+     * @return stubber - to select a method for stubbing
+     */
+    Stubber doCallRealMethod();
+}
diff --git a/src/main/java/org/mockito/stubbing/Stubbing.java b/src/main/java/org/mockito/stubbing/Stubbing.java
new file mode 100644
index 0000000..4dfb2c8
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/Stubbing.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.MockingDetails;
+import org.mockito.invocation.Invocation;
+
+/**
+ * Stubbing declared on the mock object.
+ * See detailed description including sample code and use cases see javadoc for {@link MockingDetails#getStubbings()}.
+ *
+ * @since 2.2.3
+ */
+public interface Stubbing {
+
+    /**
+     * Returns the method invocation that is stubbed.
+     * E.g. in the example stubbing <code>when(mock.foo()).thenReturn(true)</code>
+     * the invocation is <code>mock.foo()</code>.
+     * <p>
+     * The invocation instance is mutable.
+     * It is not recommended to modify the state of invocation because it will influence mock behavior.
+     * <p>
+     * To understand how this method is useful, see the description at {@link MockingDetails#getStubbings()}.
+     *
+     * @since 2.2.3
+     */
+    Invocation getInvocation();
+
+    /**
+     * Informs if the stubbing was used
+     * <p>
+     * What does it mean 'used stubbing'?
+     * Stubbing like <code>when(mock.foo()).thenReturn(true)</code> is considered used
+     * when the method <code>mock.foo()</code> is actually invoked during the execution of code under test.
+     * <p>
+     * This method is used internally by Mockito to report and detect unused stubbings.
+     * Unused stubbings are dead code and should be deleted to increase clarity of tests (see {@link org.mockito.quality.MockitoHint}.
+     * <p>
+     * To understand how this method is useful, see the description at {@link MockingDetails#getStubbings()}.
+     *
+     * @since 2.2.3
+     */
+    boolean wasUsed();
+}
diff --git a/src/main/java/org/mockito/stubbing/ValidableAnswer.java b/src/main/java/org/mockito/stubbing/ValidableAnswer.java
new file mode 100644
index 0000000..382beab
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/ValidableAnswer.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+import org.mockito.invocation.InvocationOnMock;
+
+/**
+ * Allow to validate this answer is correct for the given invocation.
+ *
+ * <p>
+ * When tests use a shared answer implementation, it may happen the answer cannot be used
+ * with some methods. Implementing this interface indicate to Mockito it needs to verify the answer is compatible
+ * with the stubbed interaction.
+ * </p>
+ *
+ * <p>
+ * In the following example the answer is shared and work as expected...
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).then(doSomethingTricky());
+ *
+ * static Answer doSomethingTricky() {
+ *     return new Answer() {
+ *         Object answer(InvocationOnMock invocation) {
+ *             // tricky stuff
+ *         }
+ *     });
+ * }
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * ...then later there's some refactoring or some new code that want to use the answer,
+ * however it is not compatible anymore. In this example the answer may throw an exception because
+ * the Answer cannot work with the return type or some parameter types.
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt())).then(doSomethingTricky()); // fail at answer execution time
+ * when(mock.incompatibleMethod(anyVararg())).then(doSomethingTricky()); // fail at answer execution time
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * Instead of having an exception raised later at answer <em>execution time</em>, one can make this answer
+ * validable at <em>stub time</em> by implementing this contract.
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.incompatibleMethod(anyVararg())).then(doSomethingTricky()); // fail at answer stub time
+ *
+ * static Answer doSomethingTricky() {
+ *     return new TrickyAnswer();
+ * }
+ *
+ * class Tricky Answer implements Answer, ValidableAnswer {
+ *     public Object answer(InvocationOnMock invocation) {
+ *         // tricky stuff
+ *     }
+ *
+ *     public void validateFor(InvocationOnMock invocation) {
+ *         // perform validation for this interaction
+ *     }
+ * }
+ * </code></pre>
+ * </p>
+ *
+ * @since 2.3.8
+ */
+@Incubating
+public interface ValidableAnswer {
+
+    /**
+     * Validation of the answer at <em>stub time</em> for the given invocation.
+     *
+     * <p>
+     * This method will be called by Mockito.
+     * </p>
+     *
+     * <p>
+     * The implementation must throw an MockitoException to indicate that this answer is not valid for
+     * the given invocation. If the validation succeed the implementation must simply return without throwing.
+     * </p>
+     *
+     * @param invocation The stubbed invocation
+     *
+     * @since 2.3.8
+     */
+    void validateFor(InvocationOnMock invocation);
+
+}
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer1.java b/src/main/java/org/mockito/stubbing/VoidAnswer1.java
new file mode 100644
index 0000000..800b136
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer1.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a single argument invocation that returns nothing.
+ *
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer&lt;String&gt;() {
+ *     void answer(String msg) {
+ *         throw new Exception(msg);
+ *     }
+ * });
+ *
+ * //Following will raise an exception with the message "boom"
+ * mock.someMethod("boom");
+ * </code></pre>
+ *
+ * @param <A0> type of the single argument
+ * @see Answer
+ */
+@Incubating
+public interface VoidAnswer1<A0> {
+    /**
+     * @param argument0 the single argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer2.java b/src/main/java/org/mockito/stubbing/VoidAnswer2.java
new file mode 100644
index 0000000..923f4da
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer2.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a two argument invocation that returns nothing.
+ *
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt())).thenAnswer(new Answer&lt;String, Integer&gt;() {
+ *     void answer(String msg, Integer count) {
+ *         throw new Exception(String.format(msg, count));
+ *     }
+ * });
+ *
+ * //Following will raise an exception with the message "boom 3"
+ * mock.someMethod("boom %d", 3);
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @see Answer
+ */
+@Incubating
+public interface VoidAnswer2<A0, A1> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer3.java b/src/main/java/org/mockito/stubbing/VoidAnswer3.java
new file mode 100644
index 0000000..281d1fe
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer3.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a three argument invocation that returns nothing.
+ *
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt(), anyString())).thenAnswer(new Answer&lt;String, Integer, String&gt;() {
+ *     void answer(String msg, Integer count, String another) {
+ *         throw new Exception(String.format(msg, another, count));
+ *     }
+ * });
+ *
+ * //Following will raise an exception with the message "ka-boom 3"
+ * mock.someMethod("%s-boom %d", 3, "ka");
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @see Answer
+ */
+@Incubating
+public interface VoidAnswer3<A0, A1, A2> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1, A2 argument2) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer4.java b/src/main/java/org/mockito/stubbing/VoidAnswer4.java
new file mode 100644
index 0000000..9e62c5c
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer4.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a four argument invocation that returns nothing.
+ *
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt(), anyString(), anyChar())).thenAnswer(
+ *     new Answer&lt;String, Integer, String, Character&gt;() {
+ *         void answer(String msg, Integer count, String another, Character c) {
+ *             throw new Exception(String.format(msg, another, c, count));
+ *         }
+ *     });
+ *
+ * //Following will raise an exception with the message "ka-boom <3"
+ * mock.someMethod("%s-boom %c%d", 3, "ka", '&lt;');
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @see Answer
+ */
+@Incubating
+public interface VoidAnswer4<A0, A1, A2, A3> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer5.java b/src/main/java/org/mockito/stubbing/VoidAnswer5.java
new file mode 100644
index 0000000..4d30e5b
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer5.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Incubating;
+
+/**
+ * Generic interface to be used for configuring mock's answer for a five argument invocation that returns nothing.
+ *
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt(), anyString(), anyChar(), anyString())).thenAnswer(
+ *     new Answer&lt;String, Integer, String, Character&gt;() {
+ *         void answer(String msg, Integer count, String another, Character c, String subject) {
+ *             throw new Exception(String.format(msg, another, c, count, subject));
+ *         }
+ *     });
+ *
+ * //Following will raise an exception with the message "ka-boom <3 mockito"
+ * mock.someMethod("%s-boom %c%d %s", 3, "ka", '&lt;', "mockito");
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @param <A4> type of the fifth argument
+ * @see Answer
+ */
+@Incubating
+public interface VoidAnswer5<A0, A1, A2, A3, A4> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     * @param argument4 the fifth argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3, A4 argument4) throws Throwable;
+}
diff --git a/src/main/java/org/mockito/stubbing/VoidMethodStubbable.java b/src/main/java/org/mockito/stubbing/VoidMethodStubbable.java
deleted file mode 100644
index f6f7323..0000000
--- a/src/main/java/org/mockito/stubbing/VoidMethodStubbable.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.stubbing;

-

-import org.mockito.Mockito;

-

-/**

- * Stubs void method with an exception. E.g:

- *

- * <pre class="code"><code class="java">

- * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod();

- *

- * //you can stub with different behavior for consecutive method calls.

- * //Last stubbing (e.g: toReturn()) determines the behavior for further consecutive calls.

- * stubVoid(mock)

- *  .toThrow(new RuntimeException())

- *  .toReturn()

- *  .on().someMethod();

- * </code></pre>

- *

- * See examples in javadoc for {@link Mockito#stubVoid}

- */

-public interface VoidMethodStubbable<T> {

-

-    /**

-     * Stubs void method with an exception. E.g:

-     *

-     * <pre class="code"><code class="java">

-     * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod();

-     * </code></pre>

-     *

-     * If throwable is a checked exception then it has to

-     * match one of the checked exceptions of method signature.

-     *

-     * See examples in javadoc for {@link Mockito#stubVoid}

-     *

-     * @param throwable to be thrown on method invocation

-     *

-     * @return VoidMethodStubbable - typically to choose void method and finish stubbing

-     */

-    VoidMethodStubbable<T> toThrow(Throwable throwable);

-

-    /**

-     * Stubs void method to 'just return' (e.g. to <b>not</b> to throw any exception)

-     * <p>

-     * <b>Only use this method if you're stubbing consecutive calls.</b>

-     * <p>

-     * For example:

-     * <pre class="code"><code class="java">

-     * stubVoid(mock)

-     *   .toReturn()

-     *   .toThrow(new RuntimeException())

-     *   .on().foo(10);

-     * </code></pre>

-     * <ul>

-     * <li>first time foo(10) is called the mock will 'just return' (e.g. don't throw any exception)</li>

-     * <li>second time foo(10) is called the mock will throw RuntimeException</li>

-     * <li>every consecutive time foo(10) is called the mock will throw RuntimeException</li>

-     * </ul>

-     * <p>

-     * See examples in javadoc for {@link Mockito#stubVoid}

-     *

-     * @return VoidMethodStubbable - typically to choose void method and finish stubbing

-     */

-    VoidMethodStubbable<T> toReturn();

-

-    /**

-     * Stubs a void method with generic {@link Answer}

-     * <p>

-     * For Example:

-     * <pre class="code"><code class="java">

-     * stubVoid(mock)

-     *   .toAnswer(new Answer() {

-     *                 public Object answer(InvocationOnMOck invocation) {

-     *                     Visitor v = (Visitor) invocation.getArguments()[0];

-     *                     v.visitMock(invocation.getMock());

-     *

-     *                     return null;

-     *                 }

-     *             })

-     *    .on().accept(any());

-     * </code></pre>

-     *

-     * @param answer the custom answer to execute.

-     *

-     * @return VoidMethodStubbable - typically to choose void method and finish stubbing

-     */

-    VoidMethodStubbable<T> toAnswer(Answer<?> answer);

-

-    /**

-     * Choose void method for stubbing. E.g:

-     *

-     * <pre class="code"><code class="java">

-     * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod("some arg");

-     * </code></pre>

-     *

-     * See examples in javadoc for {@link Mockito#stubVoid}

-     *

-     * @return mock object itself

-     */

-    T on();

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/stubbing/answers/ReturnsElementsOf.java b/src/main/java/org/mockito/stubbing/answers/ReturnsElementsOf.java
deleted file mode 100644
index efaf2f9..0000000
--- a/src/main/java/org/mockito/stubbing/answers/ReturnsElementsOf.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2007 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockito.stubbing.answers;

-

-import java.util.Collection;

-

-/**

- * Returns elements of the collection. Keeps returning the last element forever.

- * Might be useful on occasion when you have a collection of elements to return.

- * <p>

- * <pre class="code"><code class="java">

- *   //this:

- *   when(mock.foo()).thenReturn(1, 2, 3);

- *   //is equivalent to:

- *   when(mock.foo()).thenReturn(new ReturnsElementsOf(Arrays.asList(1, 2, 3)));

- * </code></pre>

- *

- * @deprecated Use {@link org.mockito.AdditionalAnswers#returnsElementsOf}

- */

-@Deprecated

-public class ReturnsElementsOf extends org.mockito.internal.stubbing.answers.ReturnsElementsOf {

-

-    @Deprecated

-    public ReturnsElementsOf(Collection<?> elements) {

-        super(elements);

-    }

-}
\ No newline at end of file
diff --git a/src/main/java/org/mockito/stubbing/package-info.java b/src/main/java/org/mockito/stubbing/package-info.java
new file mode 100644
index 0000000..220146a
--- /dev/null
+++ b/src/main/java/org/mockito/stubbing/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Stubbing related classes.
+ */
+package org.mockito.stubbing;
diff --git a/src/main/java/org/mockito/stubbing/package.html b/src/main/java/org/mockito/stubbing/package.html
deleted file mode 100644
index 55e28cc..0000000
--- a/src/main/java/org/mockito/stubbing/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
-  ~ Copyright (c) 2007 Mockito contributors
-  ~ This program is made available under the terms of the MIT License.
-  -->
-
-<body>
-External stubbing related classes 
-</body>
\ No newline at end of file
diff --git a/src/main/java/org/mockito/verification/After.java b/src/main/java/org/mockito/verification/After.java
index 07d3122..a8eeafa 100644
--- a/src/main/java/org/mockito/verification/After.java
+++ b/src/main/java/org/mockito/verification/After.java
@@ -1,15 +1,21 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
 package org.mockito.verification;
 
+import org.mockito.internal.verification.VerificationModeFactory;
 import org.mockito.internal.verification.VerificationOverTimeImpl;
+import org.mockito.internal.verification.VerificationWrapper;
 
 /**
  * See the javadoc for {@link VerificationAfterDelay}
  * <p>
  * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.
  * See javadoc for {@link VerificationWithTimeout}
- */  
+ */
 public class After extends VerificationWrapper<VerificationOverTimeImpl> implements VerificationAfterDelay {
-    
+
     /**
      * See the javadoc for {@link VerificationAfterDelay}
      * <p>
@@ -19,14 +25,22 @@
     public After(long delayMillis, VerificationMode verificationMode) {
         this(10, delayMillis, verificationMode);
     }
-    
-    public After(long pollingPeriod, long delayMillis, VerificationMode verificationMode) {
-        super(new VerificationOverTimeImpl(pollingPeriod, delayMillis, verificationMode, false));
-    }
-    
-    @Override
-    protected VerificationMode copySelfWithNewVerificationMode(VerificationMode verificationMode) {
-        return new After(wrappedVerification.getPollingPeriod(), wrappedVerification.getDuration(), verificationMode);
+
+    After(long pollingPeriod, long delayMillis, VerificationMode verificationMode) {
+        this(new VerificationOverTimeImpl(pollingPeriod, delayMillis, verificationMode, false));
     }
 
+    After(VerificationOverTimeImpl verificationOverTime) {
+        super(verificationOverTime);
+    }
+
+    @Override
+    protected VerificationMode copySelfWithNewVerificationMode(VerificationMode verificationMode) {
+        return new After(wrappedVerification.copyWithVerificationMode(verificationMode));
+    }
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
 }
diff --git a/src/main/java/org/mockito/verification/Timeout.java b/src/main/java/org/mockito/verification/Timeout.java
index d8e87ba..c918d0f 100644
--- a/src/main/java/org/mockito/verification/Timeout.java
+++ b/src/main/java/org/mockito/verification/Timeout.java
@@ -1,57 +1,68 @@
-/*

- * Copyright (c) 2007 Mockito contributors

- * This program is made available under the terms of the MIT License.

- */

-package org.mockito.verification;

-

-import org.mockito.exceptions.Reporter;

-import org.mockito.internal.util.Timer;

-import org.mockito.internal.verification.VerificationOverTimeImpl;

-/**

- * See the javadoc for {@link VerificationWithTimeout}

- * <p>

- * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.

- * See javadoc for {@link VerificationWithTimeout}

- */

-public class Timeout extends VerificationWrapper<VerificationOverTimeImpl> implements VerificationWithTimeout {

-    

-    /**

-     * See the javadoc for {@link VerificationWithTimeout}

-     * <p>

-     * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.

-     * See javadoc for {@link VerificationWithTimeout}

-     */

-    public Timeout(long millis, VerificationMode delegate) {

-        this(10, millis, delegate);

-    }

-

-    /**

-     * See the javadoc for {@link VerificationWithTimeout}

-     */

-    Timeout(long pollingPeriodMillis, long millis, VerificationMode delegate) {

-        super(new VerificationOverTimeImpl(pollingPeriodMillis, millis, delegate, true));

-    }

-

-    /**

-     * See the javadoc for {@link VerificationWithTimeout}

-     */

-    Timeout(long pollingPeriodMillis, long millis, VerificationMode delegate, Timer timer) {

-        super(new VerificationOverTimeImpl(pollingPeriodMillis, millis, delegate, true, timer));

-    }

-    

-    @Override

-    protected VerificationMode copySelfWithNewVerificationMode(VerificationMode newVerificationMode) {

-        return new Timeout(wrappedVerification.getPollingPeriod(), wrappedVerification.getDuration(), newVerificationMode);

-    }

-    

-    public VerificationMode atMost(int maxNumberOfInvocations) {

-        new Reporter().atMostAndNeverShouldNotBeUsedWithTimeout();

-        return null;

-    }

-

-    public VerificationMode never() {

-        new Reporter().atMostAndNeverShouldNotBeUsedWithTimeout();

-        return null;

-    }

-

-}
\ No newline at end of file
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.verification;
+
+import static org.mockito.internal.exceptions.Reporter.atMostAndNeverShouldNotBeUsedWithTimeout;
+
+import org.mockito.internal.util.Timer;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.internal.verification.VerificationOverTimeImpl;
+import org.mockito.internal.verification.VerificationWrapper;
+
+/**
+ * See the javadoc for {@link VerificationWithTimeout}
+ * <p>
+ * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.
+ * See javadoc for {@link VerificationWithTimeout}
+ */
+public class Timeout extends VerificationWrapper<VerificationOverTimeImpl> implements VerificationWithTimeout {
+
+    /**
+     * See the javadoc for {@link VerificationWithTimeout}
+     * <p>
+     * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.
+     * See javadoc for {@link VerificationWithTimeout}
+     */
+    public Timeout(long millis, VerificationMode delegate) {
+        this(10, millis, delegate);
+    }
+
+    /**
+     * See the javadoc for {@link VerificationWithTimeout}
+     */
+    Timeout(long pollingPeriodMillis, long millis, VerificationMode delegate) {
+        this(new VerificationOverTimeImpl(pollingPeriodMillis, millis, delegate, true));
+    }
+
+    /**
+     * See the javadoc for {@link VerificationWithTimeout}
+     */
+    Timeout(long pollingPeriodMillis, VerificationMode delegate, Timer timer) {
+        this(new VerificationOverTimeImpl(pollingPeriodMillis, delegate, true, timer));
+    }
+
+    Timeout(VerificationOverTimeImpl verificationOverTime) {
+        super(verificationOverTime);
+    }
+
+    @Override
+    protected VerificationMode copySelfWithNewVerificationMode(VerificationMode newVerificationMode) {
+        return new Timeout(wrappedVerification.copyWithVerificationMode(newVerificationMode));
+    }
+
+    public VerificationMode atMost(int maxNumberOfInvocations) {
+        throw atMostAndNeverShouldNotBeUsedWithTimeout();
+    }
+
+    public VerificationMode never() {
+        throw atMostAndNeverShouldNotBeUsedWithTimeout();
+    }
+
+    @Override
+    public VerificationMode description(String description) {
+        return VerificationModeFactory.description(this, description);
+    }
+
+}
diff --git a/src/main/java/org/mockito/verification/VerificationAfterDelay.java b/src/main/java/org/mockito/verification/VerificationAfterDelay.java
index 0df0f05..b48cb6b 100644
--- a/src/main/java/org/mockito/verification/VerificationAfterDelay.java
+++ b/src/main/java/org/mockito/verification/VerificationAfterDelay.java
@@ -9,56 +9,56 @@
 
 
 /**
- * VerificationAfterDelay is a {@link VerificationMode} that allows combining existing verification modes with an initial delay, e.g. 
+ * VerificationAfterDelay is a {@link VerificationMode} that allows combining existing verification modes with an initial delay, e.g.
  * <pre class="code"><code class="java">
  * verify(mock, after(100).atMost(5)).foo();
- * 
+ *
  * verify(mock, after(100).never()).bar();
- * 
+ *
  * verify(mock, after(200).atLeastOnce()).baz();
  * </code></pre>
- * 
- * This is similar to {@link VerificationWithTimeout timeout()} except the assertion will not terminate until either the condition is 
+ *
+ * This is similar to {@link VerificationWithTimeout timeout()} except the assertion will not terminate until either the condition is
  * definitively failed, or the full time has elapsed (whereas timeout() will also stop if the conditions is true at any point, as is
- * typically the case with never() etc initially). 
- * 
+ * typically the case with never() etc initially).
+ *
  * <p>
  * See examples in javadoc for {@link Mockito#verify(Object, VerificationMode)}
  *
  */
 public interface VerificationAfterDelay extends VerificationMode {
-    
+
     /**
      * Verifies that there are exactly N invocations during the given period. This will wait the full period given.
      */
-    public VerificationMode times(int wantedNumberOfInvocations);
+    VerificationMode times(int wantedNumberOfInvocations);
 
     /**
-     * Allows verification that there are no invocations at any point during the given period. This will wait the 
+     * Allows verification that there are no invocations at any point during the given period. This will wait the
      * full period given, unless an invocation occurs (in which case there will be immediate failure)
      */
-    public VerificationMode never();
-    
+    VerificationMode never();
+
     /**
      * Verifies that there is at least 1 invocation during the given period. This will wait the full period given.
      */
-    public VerificationMode atLeastOnce();
-    
+    VerificationMode atLeastOnce();
+
     /**
      * Verifies that there is are least N invocations during the given period. This will wait the full period given.
      */
-    public VerificationMode atLeast(int minNumberOfInvocations);
-    
+    VerificationMode atLeast(int minNumberOfInvocations);
+
     /**
      * Verifies that there is are most N invocations during the given period. This will wait the full period given,
      * unless too many invocations occur (in which case there will be an immediate failure)
      */
-    public VerificationMode atMost(int maxNumberOfInvocations);
-    
+    VerificationMode atMost(int maxNumberOfInvocations);
+
     /**
-     * Verifies that there the given method is invoked and is the only method invoked. This will wait the full 
+     * Verifies that there the given method is invoked and is the only method invoked. This will wait the full
      * period given, unless another method is invoked (in which case there will be an immediate failure)
      */
-    public VerificationMode only();
-    
+    VerificationMode only();
+
 }
diff --git a/src/main/java/org/mockito/verification/VerificationEvent.java b/src/main/java/org/mockito/verification/VerificationEvent.java
new file mode 100644
index 0000000..fa637d7
--- /dev/null
+++ b/src/main/java/org/mockito/verification/VerificationEvent.java
@@ -0,0 +1,33 @@
+package org.mockito.verification;
+
+import org.mockito.Incubating;
+import org.mockito.internal.verification.api.VerificationData;
+
+/**
+ * Contains all information about a verification that has happened.
+ */
+@Incubating
+public interface VerificationEvent {
+    /**
+     * @return The mock that a verification happened on.
+     */
+    Object getMock();
+
+    /**
+     * @return the {@link VerificationMode} that was used.
+     */
+    VerificationMode getMode();
+
+    /**
+     * @return the {@link VerificationData} that was verified on.
+     */
+    VerificationData getData();
+
+    /**
+     * A nullable Throwable if it is null, the verification succeeded,
+     * otherwise the throwable contains the cause of why the verification failed.
+     *
+     * @return null or the error.
+     */
+    Throwable getVerificationError();
+}
diff --git a/src/main/java/org/mockito/verification/VerificationMode.java b/src/main/java/org/mockito/verification/VerificationMode.java
index a436d97..2a04ad5 100644
--- a/src/main/java/org/mockito/verification/VerificationMode.java
+++ b/src/main/java/org/mockito/verification/VerificationMode.java
@@ -11,26 +11,36 @@
 /**
  * Allows verifying that certain behavior happened at least once / exact number
  * of times / never. E.g:
- * 
+ *
  * <pre class="code"><code class="java">
  * verify(mock, times(5)).someMethod(&quot;was called five times&quot;);
- * 
+ *
  * verify(mock, never()).someMethod(&quot;was never called&quot;);
- * 
+ *
  * verify(mock, atLeastOnce()).someMethod(&quot;was called at least once&quot;);
- * 
+ *
  * verify(mock, atLeast(2)).someMethod(&quot;was called at least twice&quot;);
- * 
+ *
  * verify(mock, atMost(3)).someMethod(&quot;was called at most 3 times&quot;);
- * 
+ *
  * </code></pre>
- * 
+ *
  * <b>times(1) is the default</b> and can be omitted
  * <p>
  * See examples in javadoc for {@link Mockito#verify(Object, VerificationMode)}
  */
 public interface VerificationMode {
-    
+
+    /**
+     * Performs the verification
+     */
     void verify(VerificationData data);
-    
-}
\ No newline at end of file
+
+    /**
+     * Description will be prepended to the assertion error if verification fails.
+     * @param description The custom failure message
+     * @return VerificationMode
+     * @since 2.1.0
+     */
+    VerificationMode description(String description);
+}
diff --git a/src/main/java/org/mockito/verification/VerificationStrategy.java b/src/main/java/org/mockito/verification/VerificationStrategy.java
new file mode 100644
index 0000000..605e415
--- /dev/null
+++ b/src/main/java/org/mockito/verification/VerificationStrategy.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.verification;
+
+/**
+ * Strategy to possibly lazily perform verifications.
+ */
+public interface VerificationStrategy {
+
+    /**
+     * Possibly wrap the given VerificationMode and return a wrapping
+     * VerificationMode instead.
+     *
+     * @param mode The original mode.
+     * @return A wrapping mode that uses the original mode.
+     */
+    VerificationMode maybeVerifyLazily(VerificationMode mode);
+}
diff --git a/src/main/java/org/mockito/verification/VerificationWithTimeout.java b/src/main/java/org/mockito/verification/VerificationWithTimeout.java
index 2e54933..0a4f533 100644
--- a/src/main/java/org/mockito/verification/VerificationWithTimeout.java
+++ b/src/main/java/org/mockito/verification/VerificationWithTimeout.java
@@ -9,54 +9,38 @@
 
 /**
  * VerificationWithTimeout is a {@link VerificationMode} that allows combining existing verification modes with 'timeout'. E.g:
- * 
+ *
  * <pre class="code"><code class="java">
  * verify(mock, timeout(100).times(5)).foo();
- * 
+ *
  * verify(mock, timeout(100).never()).bar();
- * 
+ *
  * verify(mock, timeout(200).atLeastOnce()).baz();
  * </code></pre>
- * 
+ *
  * This is similar to {@link VerificationAfterDelay after()} except this assertion will immediately pass if it becomes true at any point,
- * whereas after() will wait the full period. Assertions which are consistently expected to be initially true and potentially become false 
+ * whereas after() will wait the full period. Assertions which are consistently expected to be initially true and potentially become false
  * are deprecated below, and after() should be used instead.
- * 
+ *
  * <p>
  * See examples in javadoc for {@link Mockito#verify(Object, VerificationMode)}
  */
 public interface VerificationWithTimeout extends VerificationMode {
-        
+
     /**
      * Allows verifying exact number of invocations within given timeout
      * <pre class="code"><code class="java">
      *   verify(mock, timeout(100).times(2)).someMethod("some arg");
      * </code></pre>
-     * 
+     *
      * See examples in javadoc for {@link Mockito} class
-     * 
-     * @param wantedNumberOfInvocations wanted number of invocations 
-     * 
+     *
+     * @param wantedNumberOfInvocations wanted number of invocations
+     *
      * @return verification mode
      */
-    public VerificationMode times(int wantedNumberOfInvocations);
-    
-    /**
-     * @deprecated
-     * Validation with timeout combined with never simply does not make sense, as never() will typically immediately pass,
-     * and therefore not wait the timeout. The behaviour you may be looking for is actually provided by after().never(). 
-     * <p>
-     * To avoid compilation errors upon upgrade the method is deprecated and it throws a "friendly reminder" exception.
-     * <p>
-     * In a future release we will remove timeout(x).atMost(y) and timeout(x).never() from the API.
-     * <p>
-     * Do you want to find out more? See <a href="http://code.google.com/p/mockito/issues/detail?id=235">issue 235</a>
-     * 
-     * @return verification mode
-     */
-    @Deprecated    
-    public VerificationMode never();
-    
+    VerificationMode times(int wantedNumberOfInvocations);
+
     /**
      * Allows at-least-once verification within given timeout. E.g:
      * <pre class="code"><code class="java">
@@ -65,42 +49,24 @@
      * Alias to atLeast(1)
      * <p>
      * See examples in javadoc for {@link Mockito} class
-     * 
+     *
      * @return verification mode
      */
-    public VerificationMode atLeastOnce();
+    VerificationMode atLeastOnce();
 
     /**
      * Allows at-least-x verification within given timeout. E.g:
      * <pre class="code"><code class="java">
      *   verify(mock, timeout(100).atLeast(3)).someMethod("some arg");
      * </code></pre>
-     * 
+     *
      * See examples in javadoc for {@link Mockito} class
-     * 
-     * @param minNumberOfInvocations minimum number of invocations 
-     * 
-     * @return verification mode
-     */
-    public VerificationMode atLeast(int minNumberOfInvocations);
-
-    /**
-     * @deprecated
      *
-     * <b>Deprecated</b>
-     * Validation with timeout combined with never simply does not make sense, as atMost() will typically immediately pass,
-     * and therefore not wait the timeout. The behaviour you may be looking for is actually provided by after().atMost(). 
-     * <p>
-     * To avoid compilation errors upon upgrade the method is deprecated and it throws a "friendly reminder" exception.
-     * <p>
-     * In a future release we will remove timeout(x).atMost(y) and timeout(x).never() from the API.
-     * <p>
-     * Do you want to find out more? See <a href="http://code.google.com/p/mockito/issues/detail?id=235">issue 235</a>
+     * @param minNumberOfInvocations minimum number of invocations
      *
      * @return verification mode
      */
-    @Deprecated
-    public VerificationMode atMost(int maxNumberOfInvocations);
+    VerificationMode atLeast(int minNumberOfInvocations);
 
     /**
      * Allows checking if given method was the only one invoked. E.g:
@@ -108,15 +74,15 @@
      *   verify(mock, only()).someMethod();
      *   //above is a shorthand for following 2 lines of code:
      *   verify(mock).someMethod();
-     *   verifyNoMoreInvocations(mock);
+     *   verifyNoMoreInteractions(mock);
      * </code></pre>
-     * 
+     *
      * <p>
      * See also {@link Mockito#verifyNoMoreInteractions(Object...)}
      * <p>
      * See examples in javadoc for {@link Mockito} class
-     * 
+     *
      * @return verification mode
      */
-    public VerificationMode only();       
-}
\ No newline at end of file
+    VerificationMode only();
+}
diff --git a/src/main/java/org/mockito/verification/VerificationWrapper.java b/src/main/java/org/mockito/verification/VerificationWrapper.java
deleted file mode 100644
index d32fab2..0000000
--- a/src/main/java/org/mockito/verification/VerificationWrapper.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.mockito.verification;
-
-import org.mockito.internal.verification.VerificationModeFactory;
-import org.mockito.internal.verification.api.VerificationData;
-
-public abstract class VerificationWrapper<WrapperType extends VerificationMode> implements VerificationMode {
-
-    protected final WrapperType wrappedVerification;
-
-    public VerificationWrapper(WrapperType wrappedVerification) {
-        this.wrappedVerification = wrappedVerification;
-    }
-
-    public void verify(VerificationData data) {
-        wrappedVerification.verify(data);
-    } 
-    
-    protected abstract VerificationMode copySelfWithNewVerificationMode(VerificationMode verificationMode);
-
-    public VerificationMode times(int wantedNumberOfInvocations) {
-        return copySelfWithNewVerificationMode(VerificationModeFactory.times(wantedNumberOfInvocations));
-    }
-    
-    public VerificationMode never() {
-        return copySelfWithNewVerificationMode(VerificationModeFactory.atMost(0));
-    }
-
-    public VerificationMode atLeastOnce() {
-        return copySelfWithNewVerificationMode(VerificationModeFactory.atLeastOnce());
-    }
-
-    public VerificationMode atLeast(int minNumberOfInvocations) {
-        return copySelfWithNewVerificationMode(VerificationModeFactory.atLeast(minNumberOfInvocations));
-    }
-
-    public VerificationMode atMost(int maxNumberOfInvocations) {
-        return copySelfWithNewVerificationMode(VerificationModeFactory.atMost(maxNumberOfInvocations));
-    }
-
-    public VerificationMode only() {
-        return copySelfWithNewVerificationMode(VerificationModeFactory.only());
-    }
-    
-}
diff --git a/src/main/java/org/mockito/verification/package-info.java b/src/main/java/org/mockito/verification/package-info.java
new file mode 100644
index 0000000..54deaca
--- /dev/null
+++ b/src/main/java/org/mockito/verification/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Verification related classes.
+ */
+package org.mockito.verification;
diff --git a/src/test/java/org/concurrentmockito/ThreadVerifiesContinuoslyInteractingMockTest.java b/src/test/java/org/concurrentmockito/ThreadVerifiesContinuoslyInteractingMockTest.java
new file mode 100644
index 0000000..0f91bb3
--- /dev/null
+++ b/src/test/java/org/concurrentmockito/ThreadVerifiesContinuoslyInteractingMockTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.concurrentmockito;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.verify;
+
+//this test exposes the problem most of the time
+public class ThreadVerifiesContinuoslyInteractingMockTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Test
+    public void shouldAllowVerifyingInThreads() throws Exception {
+        for(int i = 0; i < 100; i++) {
+            performTest();
+        }
+    }
+
+    private void performTest() throws InterruptedException {
+        mock.simpleMethod();
+        final Thread[] listeners = new Thread[2];
+        for (int i = 0; i < listeners.length; i++) {
+            final int x = i;
+            listeners[i] = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        Thread.sleep(x * 10);
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
+                    mock.simpleMethod();
+                }
+            };
+            listeners[i].start();
+        }
+
+        verify(mock, atLeastOnce()).simpleMethod();
+
+        for (Thread listener : listeners) {
+            listener.join();
+        }
+    }
+}
diff --git a/src/test/java/org/concurrentmockito/ThreadsRunAllTestsHalfManualTest.java b/src/test/java/org/concurrentmockito/ThreadsRunAllTestsHalfManualTest.java
new file mode 100644
index 0000000..989141c
--- /dev/null
+++ b/src/test/java/org/concurrentmockito/ThreadsRunAllTestsHalfManualTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.concurrentmockito;
+
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.mockito.MockitoTest;
+import org.mockito.internal.exceptions.ReporterTest;
+import org.mockito.exceptions.base.MockitoAssertionErrorTest;
+import org.mockito.exceptions.base.MockitoExceptionTest;
+import org.mockito.internal.AllInvocationsFinderTest;
+import org.mockito.internal.InvalidStateDetectionTest;
+import org.mockito.internal.creation.bytebuddy.TypeCachingMockBytecodeGeneratorTest;
+import org.mockito.internal.handler.MockHandlerImplTest;
+import org.mockito.internal.invocation.InvocationImplTest;
+import org.mockito.internal.invocation.InvocationMatcherTest;
+import org.mockito.internal.invocation.InvocationsFinderTest;
+import org.mockito.internal.matchers.ComparableMatchersTest;
+import org.mockito.internal.matchers.EqualsTest;
+import org.mockito.internal.matchers.MatchersToStringTest;
+import org.mockito.internal.progress.MockingProgressImplTest;
+import org.mockito.internal.progress.TimesTest;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValuesTest;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsGenericDeepStubsTest;
+import org.mockito.internal.util.MockUtilTest;
+import org.mockito.internal.util.collections.ListUtilTest;
+import org.mockito.internal.verification.DefaultRegisteredInvocationsTest;
+import org.mockito.internal.verification.checkers.MissingInvocationCheckerTest;
+import org.mockito.internal.verification.checkers.MissingInvocationInOrderCheckerTest;
+import org.mockito.internal.verification.checkers.NumberOfInvocationsCheckerTest;
+import org.mockito.internal.verification.checkers.NumberOfInvocationsInOrderCheckerTest;
+import org.mockitousage.basicapi.ReplacingObjectMethodsTest;
+import org.mockitousage.basicapi.ResetTest;
+import org.mockitousage.basicapi.UsingVarargsTest;
+import org.mockitousage.examples.use.ExampleTest;
+import org.mockitousage.matchers.CustomMatchersTest;
+import org.mockitousage.matchers.InvalidUseOfMatchersTest;
+import org.mockitousage.matchers.MatchersTest;
+import org.mockitousage.matchers.VerificationAndStubbingUsingMatchersTest;
+import org.mockitousage.misuse.InvalidUsageTest;
+import org.mockitousage.puzzlers.BridgeMethodPuzzleTest;
+import org.mockitousage.puzzlers.OverloadingPuzzleTest;
+import org.mockitousage.stacktrace.ClickableStackTracesTest;
+import org.mockitousage.stacktrace.PointingStackTraceToActualInvocationTest;
+import org.mockitousage.stacktrace.StackTraceFilteringTest;
+import org.mockitousage.stubbing.BasicStubbingTest;
+import org.mockitousage.stubbing.ReturningDefaultValuesTest;
+import org.mockitousage.stubbing.StubbingWithThrowablesTest;
+import org.mockitousage.verification.*;
+import org.mockitoutil.TestBase;
+
+import java.util.*;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+
+public class ThreadsRunAllTestsHalfManualTest extends TestBase {
+
+    private static class AllTestsRunner extends Thread {
+
+        private Set<Class<?>> failed = new HashSet<Class<?>>();
+
+        public void run() {
+            Result result = JUnitCore.runClasses(
+                    EqualsTest.class,
+                    ListUtilTest.class,
+                    MockingProgressImplTest.class,
+                    TimesTest.class,
+                    MockHandlerImplTest.class,
+                    AllInvocationsFinderTest.class,
+                    ReturnsEmptyValuesTest.class,
+                    NumberOfInvocationsCheckerTest.class,
+                    DefaultRegisteredInvocationsTest.class,
+                    MissingInvocationCheckerTest.class,
+                    NumberOfInvocationsInOrderCheckerTest.class,
+                    MissingInvocationInOrderCheckerTest.class,
+                    TypeCachingMockBytecodeGeneratorTest.class,
+                    InvocationMatcherTest.class,
+                    InvocationsFinderTest.class,
+                    InvocationImplTest.class,
+                    MockitoTest.class,
+                    MockUtilTest.class,
+                    ReporterTest.class,
+                    MockitoAssertionErrorTest.class,
+                    MockitoExceptionTest.class,
+                    StackTraceFilteringTest.class,
+                    BridgeMethodPuzzleTest.class,
+                    OverloadingPuzzleTest.class,
+                    InvalidUsageTest.class,
+                    UsingVarargsTest.class,
+                    CustomMatchersTest.class,
+                    ComparableMatchersTest.class,
+                    InvalidUseOfMatchersTest.class,
+                    MatchersTest.class,
+                    MatchersToStringTest.class,
+                    VerificationAndStubbingUsingMatchersTest.class,
+                    BasicStubbingTest.class,
+                    ReturningDefaultValuesTest.class,
+                    StubbingWithThrowablesTest.class,
+                    AtMostXVerificationTest.class,
+                    BasicVerificationTest.class,
+                    ExactNumberOfTimesVerificationTest.class,
+                    VerificationInOrderTest.class,
+                    NoMoreInteractionsVerificationTest.class,
+                    SelectedMocksInOrderVerificationTest.class,
+                    VerificationOnMultipleMocksUsingMatchersTest.class,
+                    VerificationUsingMatchersTest.class,
+                    RelaxedVerificationInOrderTest.class,
+                    DescriptiveMessagesWhenVerificationFailsTest.class,
+                    DescriptiveMessagesWhenTimesXVerificationFailsTest.class,
+                    BasicVerificationInOrderTest.class,
+                    VerificationInOrderMixedWithOrdiraryVerificationTest.class,
+                    DescriptiveMessagesOnVerificationInOrderErrorsTest.class,
+                    InvalidStateDetectionTest.class,
+                    ReplacingObjectMethodsTest.class,
+                    ClickableStackTracesTest.class,
+                    ExampleTest.class,
+                    PointingStackTraceToActualInvocationTest.class,
+                    VerificationInOrderFromMultipleThreadsTest.class,
+                    ResetTest.class,
+                    ReturnsGenericDeepStubsTest.class
+                );
+
+                if (!result.wasSuccessful()) {
+                    System.err.println("Thread[" + Thread.currentThread().getId() + "]: error!");
+                    List<Failure> failures = result.getFailures();
+                    System.err.println(failures.size());
+                    for (Failure failure : failures) {
+                        System.err.println(failure.getTrace());
+                        failed.add(failure.getDescription().getTestClass());
+                    }
+                }
+        }
+
+        public Set<Class<?>> getFailed() {
+            return failed;
+        }
+    }
+
+    @Test
+    public void shouldRunInMultipleThreads() throws Exception {
+        //this test ALWAYS fails if there is a single failing unit
+        assertEquals("Run in multiple thread failed for tests", Collections.emptySet(), runInMultipleThreads(3));
+    }
+
+    public static Set<Class<?>> runInMultipleThreads(int numberOfThreads) throws Exception {
+        List<AllTestsRunner> threads = new LinkedList<AllTestsRunner>();
+        for (int i = 1; i <= numberOfThreads; i++) {
+            threads.add(new AllTestsRunner());
+        }
+
+        for (Thread t : threads) {
+            t.start();
+        }
+
+        Set<Class<?>> failed = new HashSet<Class<?>>();
+        for (AllTestsRunner t : threads) {
+            t.join();
+            failed.addAll(t.getFailed());
+        }
+
+        return failed;
+    }
+
+    public static void main(String[] args) throws Exception {
+        int numberOfThreads = 20;
+        long before = System.currentTimeMillis();
+        Set<Class<?>> failed = runInMultipleThreads(numberOfThreads);
+        long after = System.currentTimeMillis();
+        long executionTime = (after-before)/1000;
+        System.out.println("Finished tests in " + numberOfThreads + " threads in " + executionTime + " seconds. (" + failed.size() + " tests failed)");
+    }
+}
diff --git a/src/test/java/org/concurrentmockito/ThreadsShareAMockTest.java b/src/test/java/org/concurrentmockito/ThreadsShareAMockTest.java
new file mode 100644
index 0000000..8854789
--- /dev/null
+++ b/src/test/java/org/concurrentmockito/ThreadsShareAMockTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.concurrentmockito;
+
+import org.junit.Test;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+public class ThreadsShareAMockTest extends TestBase {
+
+    private IMethods mock;
+
+    @Test
+    public void shouldAllowVerifyingInThreads() throws Exception {
+        for(int i = 0; i < 100; i++) {
+            performTest();
+        }
+    }
+
+    private void performTest() throws InterruptedException {
+        mock = mock(IMethods.class);
+        final Thread[] listeners = new Thread[3];
+        for (int i = 0; i < listeners.length; i++) {
+            listeners[i] = new Thread() {
+                @Override
+                public void run() {
+                    mock.simpleMethod("foo");
+                }
+            };
+            listeners[i].start();
+        }
+        for (Thread listener : listeners) {
+            listener.join();
+        }
+        verify(mock, times(listeners.length)).simpleMethod("foo");
+    }
+}
diff --git a/src/test/java/org/concurrentmockito/ThreadsShareGenerouslyStubbedMockTest.java b/src/test/java/org/concurrentmockito/ThreadsShareGenerouslyStubbedMockTest.java
new file mode 100644
index 0000000..502e205
--- /dev/null
+++ b/src/test/java/org/concurrentmockito/ThreadsShareGenerouslyStubbedMockTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.concurrentmockito;
+
+import org.junit.Test;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+//this test always passes but please keep looking sys err
+//this test should be run 10 times, manually
+public class ThreadsShareGenerouslyStubbedMockTest extends TestBase {
+
+    private IMethods mock;
+
+    @Test
+    public void shouldAllowVerifyingInThreads() throws Exception {
+        for(int i = 0; i < 50; i++) {
+            performTest();
+        }
+    }
+
+    private void performTest() throws InterruptedException {
+        mock = mock(IMethods.class);
+
+        when(mock.simpleMethod("foo"))
+            .thenReturn("foo")
+            .thenReturn("bar")
+            .thenReturn("baz")
+            .thenReturn("foo")
+            .thenReturn("bar")
+            .thenReturn("baz");
+
+        final Thread[] listeners = new Thread[100];
+        for (int i = 0; i < listeners.length; i++) {
+            listeners[i] = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        mock.simpleMethod("foo");
+                        mock.simpleMethod("foo");
+                        mock.simpleMethod("foo");
+                        mock.simpleMethod("foo");
+                        mock.simpleMethod("foo");
+                        mock.simpleMethod("foo");
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            };
+            listeners[i].start();
+        }
+        for (Thread listener : listeners) {
+            listener.join();
+        }
+    }
+}
diff --git a/src/test/java/org/concurrentmockito/VerificationInOrderFromMultipleThreadsTest.java b/src/test/java/org/concurrentmockito/VerificationInOrderFromMultipleThreadsTest.java
new file mode 100644
index 0000000..055da2d
--- /dev/null
+++ b/src/test/java/org/concurrentmockito/VerificationInOrderFromMultipleThreadsTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.concurrentmockito;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+
+public class VerificationInOrderFromMultipleThreadsTest extends TestBase {
+
+    @Test
+    public void shouldVerifyInOrderWhenMultipleThreadsInteractWithMock() throws Exception {
+        final Foo testInf = mock(Foo.class);
+
+        Thread threadOne = new Thread(new Runnable(){
+            public void run() {
+                testInf.methodOne();
+            }
+        });
+        threadOne.start();
+        threadOne.join();
+
+        Thread threadTwo = new Thread(new Runnable(){
+            public void run() {
+                testInf.methodTwo();
+            }
+        });
+        threadTwo.start();
+        threadTwo.join();
+
+        InOrder inOrder = inOrder(testInf);
+        inOrder.verify(testInf).methodOne();
+        inOrder.verify(testInf).methodTwo();
+    }
+
+    public interface Foo {
+        void methodOne();
+        void methodTwo();
+    }
+}
diff --git a/src/test/java/org/concurrentmockito/package-info.java b/src/test/java/org/concurrentmockito/package-info.java
new file mode 100644
index 0000000..598d27c
--- /dev/null
+++ b/src/test/java/org/concurrentmockito/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Unit tests of mockito, also there's stack trace filtering)
+ *
+ * {@link org.mockitousage} is for functional / acceptance tests
+ */
+package org.concurrentmockito;
diff --git a/src/test/java/org/mockito/AnnotationsAreCopiedFromMockedTypeTest.java b/src/test/java/org/mockito/AnnotationsAreCopiedFromMockedTypeTest.java
new file mode 100644
index 0000000..30485ec
--- /dev/null
+++ b/src/test/java/org/mockito/AnnotationsAreCopiedFromMockedTypeTest.java
@@ -0,0 +1,125 @@
+package org.mockito;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import static java.lang.annotation.ElementType.*;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.mock;
+
+public class AnnotationsAreCopiedFromMockedTypeTest {
+
+    @Test
+    public void mock_should_have_annotations_copied_from_mocked_type_at_class_level() {
+        AnnotationWithDefaultValue onClassDefaultValue = mock(OnClass.class).getClass().getAnnotation(AnnotationWithDefaultValue.class);
+        AnnotationWithCustomValue onClassCustomValue = mock(OnClass.class).getClass().getAnnotation(AnnotationWithCustomValue.class);
+
+        assumeTrue("Annotation copying does not apply for inline mocks", mock(OnClass.class).getClass() != OnClass.class);
+
+        Assertions.assertThat(onClassDefaultValue.value()).isEqualTo("yup");
+        Assertions.assertThat(onClassCustomValue.value()).isEqualTo("yay");
+    }
+
+    @Test
+    public void mock_should_have_annotations_copied_from_mocked_type_on_methods() {
+        AnnotationWithDefaultValue onClassDefaultValue = method("method", mock(OnMethod.class)).getAnnotation(AnnotationWithDefaultValue.class);
+        AnnotationWithCustomValue onClassCustomValue = method("method", mock(OnMethod.class)).getAnnotation(AnnotationWithCustomValue.class);
+
+        Assertions.assertThat(onClassDefaultValue.value()).isEqualTo("yup");
+        Assertions.assertThat(onClassCustomValue.value()).isEqualTo("yay");
+    }
+
+    @Test
+    public void mock_should_have_annotations_copied_from_mocked_type_on_method_parameters() {
+        AnnotationWithDefaultValue onClassDefaultValue = firstParamOf(method("method", mock(OnMethod.class))).getAnnotation(AnnotationWithDefaultValue.class);
+        AnnotationWithCustomValue onClassCustomValue = firstParamOf(method("method", mock(OnMethod.class))).getAnnotation(AnnotationWithCustomValue.class);
+
+        Assertions.assertThat(onClassDefaultValue.value()).isEqualTo("yup");
+        Assertions.assertThat(onClassCustomValue.value()).isEqualTo("yay");
+    }
+
+    private AnnotatedElement firstParamOf(Method method) {
+        final Annotation[] firstParamAnnotations = method.getParameterAnnotations()[0];
+
+        return new AnnotatedElement() {
+            @Override
+            public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+                return getAnnotation(annotationClass) != null;
+            }
+
+            @Override
+            @SuppressWarnings("unchecked")
+            public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+                for (Annotation firstParamAnnotation : firstParamAnnotations) {
+                    if (annotationClass.isAssignableFrom(firstParamAnnotation.getClass())) {
+                        return (T) firstParamAnnotation;
+                    }
+                }
+                return null;
+            }
+
+            @Override
+            public Annotation[] getAnnotations() {
+                return firstParamAnnotations;
+            }
+
+            @Override
+            public Annotation[] getDeclaredAnnotations() {
+                return firstParamAnnotations;
+            }
+        };
+    }
+
+    private Method method(String methodName, Object mock) {
+        for (Method method : mock.getClass().getDeclaredMethods()) {
+            if(methodName.equals(method.getName())) {
+                return method;
+            }
+        }
+        throw new IllegalArgumentException("method name not found : " + methodName);
+    }
+
+    private Field field(String fieldName, Object mock) {
+        for (Field field : mock.getClass().getDeclaredFields()) {
+            if(fieldName.equals(field.getName())) {
+                return field;
+            }
+        }
+        throw new IllegalArgumentException("method name not found : " + fieldName);
+    }
+
+    @AnnotationWithDefaultValue
+    @AnnotationWithCustomValue("yay")
+    public class OnClass { }
+
+
+    public class OnMethod {
+        @AnnotationWithDefaultValue
+        @AnnotationWithCustomValue("yay")
+        public String method(
+                @AnnotationWithDefaultValue
+                @AnnotationWithCustomValue("yay")
+                String ignored
+        ) { return ""; }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({TYPE, METHOD, PARAMETER, FIELD})
+    public @interface AnnotationWithDefaultValue {
+        String value() default "yup";
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({TYPE, METHOD, PARAMETER, FIELD})
+    public @interface AnnotationWithCustomValue {
+        String value() default "";
+    }
+}
diff --git a/src/test/java/org/mockito/ArgumentCaptorTest.java b/src/test/java/org/mockito/ArgumentCaptorTest.java
new file mode 100644
index 0000000..0ab5ff7
--- /dev/null
+++ b/src/test/java/org/mockito/ArgumentCaptorTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.validateMockitoUsage;
+
+public class ArgumentCaptorTest {
+
+	/**
+	 * Clean up the internal Mockito-Stubbing state
+	 */
+	@After
+	public void tearDown() {
+		try {
+			validateMockitoUsage();
+		} catch (InvalidUseOfMatchersException ignore) {
+		}
+
+	}
+
+	@Test
+	public void tell_handy_return_values_to_return_value_for() throws Exception {
+
+		ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
+		assertThat(captor.capture()).isNull();
+
+	}
+
+}
diff --git a/src/test/java/org/mockito/MockitoTest.java b/src/test/java/org/mockito/MockitoTest.java
new file mode 100644
index 0000000..3b96aff
--- /dev/null
+++ b/src/test/java/org/mockito/MockitoTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
+import java.util.List;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.creation.MockSettingsImpl;
+
+@SuppressWarnings("unchecked")
+public class MockitoTest {
+
+    @Test
+    public void shouldRemoveStubbableFromProgressAfterStubbing() {
+        List mock = Mockito.mock(List.class);
+        Mockito.when(mock.add("test")).thenReturn(true);
+        //TODO Consider to move to separate test
+        assertThat(mockingProgress().pullOngoingStubbing()).isNull();
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldValidateMockWhenVerifying() {
+        Mockito.verify("notMock");
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldValidateMockWhenVerifyingWithExpectedNumberOfInvocations() {
+        Mockito.verify("notMock", times(19));
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldValidateMockWhenVerifyingNoMoreInteractions() {
+        Mockito.verifyNoMoreInteractions("notMock");
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldValidateMockWhenVerifyingZeroInteractions() {
+        Mockito.verifyZeroInteractions("notMock");
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldValidateMockWhenCreatingInOrderObject() {
+        Mockito.inOrder("notMock");
+    }
+
+    @Test
+    public void shouldStartingMockSettingsContainDefaultBehavior() {
+        //when
+        MockSettingsImpl<?> settings = (MockSettingsImpl<?>) Mockito.withSettings();
+
+        //then
+        assertThat(Mockito.RETURNS_DEFAULTS).isEqualTo(settings.getDefaultAnswer());
+    }
+
+}
diff --git a/src/test/java/org/mockito/StateMaster.java b/src/test/java/org/mockito/StateMaster.java
new file mode 100644
index 0000000..c0100e7
--- /dev/null
+++ b/src/test/java/org/mockito/StateMaster.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import org.mockito.listeners.MockitoListener;
+
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
+public class StateMaster {
+
+    public void reset() {
+        mockingProgress().reset();
+        mockingProgress().resetOngoingStubbing();
+    }
+
+    public void validate() {
+        mockingProgress().validateState();
+    }
+
+    /**
+     * Clears Mockito listeners added by {@link MockitoFramework#addListener(MockitoListener)}
+     */
+    public void clearMockitoListeners() {
+        mockingProgress().clearListeners();
+    }
+}
diff --git a/src/test/java/org/mockito/configuration/MockitoConfiguration.java b/src/test/java/org/mockito/configuration/MockitoConfiguration.java
new file mode 100644
index 0000000..bc7df84
--- /dev/null
+++ b/src/test/java/org/mockito/configuration/MockitoConfiguration.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.configuration;
+
+import org.mockito.stubbing.Answer;
+import org.mockitousage.configuration.CustomizedAnnotationForSmartMockTest;
+
+public class MockitoConfiguration extends DefaultMockitoConfiguration implements IMockitoConfiguration {
+
+    private Answer<Object> overriddenDefaultAnswer = null;
+
+    private boolean cleansStackTrace;
+
+    private AnnotationEngine overriddenEngine;
+
+    private boolean enableClassCache = true;
+
+    //for testing purposes, allow to override the configuration
+    public void overrideDefaultAnswer(Answer<Object> defaultAnswer) {
+        this.overriddenDefaultAnswer = defaultAnswer;
+    }
+
+    //for testing purposes, allow to override the configuration
+    public void overrideCleansStackTrace(boolean cleansStackTrace) {
+        this.cleansStackTrace = cleansStackTrace;
+    }
+
+    //for testing purposes, allow to override the annotation engine
+    public void overrideAnnotationEngine(AnnotationEngine engine) {
+        this.overriddenEngine = engine;
+    }
+
+    //for testing purposes, allow to override the annotation engine
+    public void overrideEnableClassCache(boolean enableClassCache) {
+        this.enableClassCache = enableClassCache;
+    }
+
+    @Override
+    public Answer<Object> getDefaultAnswer() {
+        if (overriddenDefaultAnswer == null) {
+            return super.getDefaultAnswer();
+        } else {
+            return overriddenDefaultAnswer;
+        }
+    }
+
+    @Override
+    public AnnotationEngine getAnnotationEngine() {
+        if (this.overriddenEngine != null) {
+            return this.overriddenEngine;
+        }
+        return new CustomizedAnnotationForSmartMockTest.CustomInjectingAnnotationEngine();
+    }
+
+    @Override
+    public boolean cleansStackTrace() {
+        return cleansStackTrace;
+    }
+
+    @Override
+    public boolean enableClassCache() {
+        return enableClassCache;
+    }
+
+}
diff --git a/src/test/java/org/mockito/exceptions/base/MockitoAssertionErrorTest.java b/src/test/java/org/mockito/exceptions/base/MockitoAssertionErrorTest.java
new file mode 100644
index 0000000..b6f4d26
--- /dev/null
+++ b/src/test/java/org/mockito/exceptions/base/MockitoAssertionErrorTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class MockitoAssertionErrorTest extends TestBase {
+
+    private void throwIt() {
+        throw new MockitoAssertionError("boom");
+    }
+
+    @Test
+    public void shouldKeepUnfilteredStackTrace() {
+        try {
+            throwIt();
+            fail();
+        } catch (MockitoAssertionError e) {
+            assertEquals("throwIt", e.getUnfilteredStackTrace()[0].getMethodName());
+        }
+    }
+
+    @Test
+    public void should_prepend_message_to_original() {
+        MockitoAssertionError original = new MockitoAssertionError("original message");
+        MockitoAssertionError errorWithPrependedMessage = new MockitoAssertionError(original, "new message");
+        assertEquals("new message\noriginal message", errorWithPrependedMessage.getMessage());
+    }
+}
diff --git a/src/test/java/org/mockito/exceptions/base/MockitoExceptionTest.java b/src/test/java/org/mockito/exceptions/base/MockitoExceptionTest.java
new file mode 100644
index 0000000..07ca5f3
--- /dev/null
+++ b/src/test/java/org/mockito/exceptions/base/MockitoExceptionTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class MockitoExceptionTest extends TestBase {
+
+    private void throwIt() {
+        throw new MockitoException("boom");
+    }
+
+    @Test
+    public void shouldKeepUnfilteredStackTrace() {
+        try {
+            throwIt();
+            fail();
+        } catch (MockitoException e) {
+            assertEquals("throwIt", e.getUnfilteredStackTrace()[0].getMethodName());
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/exceptions/base/MockitoSerializationIssueTest.java b/src/test/java/org/mockito/exceptions/base/MockitoSerializationIssueTest.java
new file mode 100644
index 0000000..47db7b1
--- /dev/null
+++ b/src/test/java/org/mockito/exceptions/base/MockitoSerializationIssueTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import org.junit.Test;
+import org.mockito.internal.configuration.ConfigurationAccess;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MockitoSerializationIssueTest {
+
+    @Test
+    public void should_filter_out_test_class_from_stacktrace_when_clean_flag_is_true() {
+        // given
+        ConfigurationAccess.getConfig().overrideCleansStackTrace(true);
+
+        // when
+        MockitoSerializationIssue issue = new MockitoSerializationIssue("msg", new Exception("cause"));
+
+        // then
+        assertThat(Arrays.toString(issue.getUnfilteredStackTrace())).contains("MockitoSerializationIssueTest");
+        assertThat(Arrays.toString(issue.getStackTrace())).doesNotContain("MockitoSerializationIssueTest");
+    }
+
+    @Test
+    public void should_keep_executing_class_in_stacktrace_when_clean_flag_is_false() {
+        // given
+        ConfigurationAccess.getConfig().overrideCleansStackTrace(false);
+
+        // when
+        MockitoSerializationIssue issue = new MockitoSerializationIssue("msg", new Exception("cause"));
+
+        // then
+        assertThat(Arrays.toString(issue.getUnfilteredStackTrace())).contains("MockitoSerializationIssueTest");
+        assertThat(Arrays.toString(issue.getStackTrace())).contains("MockitoSerializationIssueTest");
+    }
+}
diff --git a/src/test/java/org/mockito/exceptions/base/StackTraceBuilder.java b/src/test/java/org/mockito/exceptions/base/StackTraceBuilder.java
new file mode 100644
index 0000000..a0bbced
--- /dev/null
+++ b/src/test/java/org/mockito/exceptions/base/StackTraceBuilder.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class StackTraceBuilder {
+
+    private String[] methods;
+
+    public StackTraceBuilder methods(String ... methods) {
+        this.methods = methods;
+        return this;
+    }
+
+    public StackTraceElement[] toStackTrace() {
+        StackTraceElement[] trace = new StackTraceElement[methods.length];
+
+        for (int i = 0; i < methods.length; i++) {
+            trace[i] = new StackTraceElement("DummyClass", methods[i], "DummyClass.java", 100);
+        }
+
+        return trace;
+    }
+
+    public List<StackTraceElement> toStackTraceList() {
+        return Arrays.asList(toStackTrace());
+    }
+}
diff --git a/src/test/java/org/mockito/exceptions/base/TraceBuilder.java b/src/test/java/org/mockito/exceptions/base/TraceBuilder.java
new file mode 100644
index 0000000..247ad38
--- /dev/null
+++ b/src/test/java/org/mockito/exceptions/base/TraceBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public class TraceBuilder {
+
+    private String[] methods = {};
+    private String[] classes = {};
+
+    public Throwable toThrowable() {
+        RuntimeException exception = new RuntimeException();
+        exception.setStackTrace(toTraceArray());
+        return exception;
+    }
+
+    private List<StackTraceElement> toTraceList() {
+        assert methods.length == 0 || classes.length == 0;
+
+        List<StackTraceElement> trace = new LinkedList<StackTraceElement>();
+        for (String method : methods) {
+            trace.add(new StackTraceElement("SomeClass", method, "SomeClass.java", 50));
+        }
+        for (String clazz : classes) {
+            trace.add(new StackTraceElement(clazz, "someMethod", clazz + ".java", 50));
+        }
+
+        Collections.reverse(trace);
+        return trace;
+    }
+
+    public StackTraceElement[] toTraceArray() {
+        return toTraceList().toArray(new StackTraceElement[0]);
+    }
+
+    public TraceBuilder classes(String ... classes) {
+        this.classes = classes;
+        return this;
+    }
+
+    public TraceBuilder methods(String ... methods) {
+        this.methods = methods;
+        return this;
+    }
+}
diff --git a/src/test/java/org/mockito/exceptions/stacktrace/StackTraceCleanerTest.java b/src/test/java/org/mockito/exceptions/stacktrace/StackTraceCleanerTest.java
new file mode 100644
index 0000000..419ac1f
--- /dev/null
+++ b/src/test/java/org/mockito/exceptions/stacktrace/StackTraceCleanerTest.java
@@ -0,0 +1,43 @@
+package org.mockito.exceptions.stacktrace;
+
+import org.junit.Test;
+import org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleaner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class StackTraceCleanerTest {
+
+    private DefaultStackTraceCleaner cleaner= new DefaultStackTraceCleaner();
+
+    @Test
+    public void allow_or_disallow_mockito_mockito_objects_in_stacktrace() throws Exception {
+        assertAcceptedInStackTrace("my.custom.Type");
+        assertRejectedInStackTrace("org.mockito.foo.Bar");
+
+        assertAcceptedInStackTrace("org.mockito.internal.junit.JUnitRule");
+
+        assertAcceptedInStackTrace("org.mockito.junit.AllTypesOfThisPackage");
+        assertAcceptedInStackTrace("org.mockito.junit.subpackage.AllTypesOfThisPackage");
+
+        assertAcceptedInStackTrace("org.mockito.runners.AllTypesOfThisPackage");
+        assertAcceptedInStackTrace("org.mockito.runners.subpackage.AllTypesOfThisPackage");
+
+        assertAcceptedInStackTrace("org.mockito.internal.runners.AllTypesOfThisPackage");
+        assertAcceptedInStackTrace("org.mockito.internal.runners.subpackage.AllTypesOfThisPackage");
+
+        assertRejectedInStackTrace("my.custom.Type$$EnhancerByMockitoWithCGLIB$$Foo");
+        assertRejectedInStackTrace("my.custom.Type$MockitoMock$Foo");
+    }
+
+    private void assertAcceptedInStackTrace(String className) {
+        assertThat(cleaner.isIn(stackTraceElementWith(className))).describedAs("Must be accepted in stacktrace %s", className).isTrue();
+    }
+
+    private void assertRejectedInStackTrace(String className) {
+        assertThat(cleaner.isIn(stackTraceElementWith(className))).describedAs("Must be rejected in stacktrace %s", className).isFalse();
+    }
+
+    private StackTraceElement stackTraceElementWith(String className) {
+        return new StackTraceElement(className, "methodName", null, -1);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/AllInvocationsFinderTest.java b/src/test/java/org/mockito/internal/AllInvocationsFinderTest.java
new file mode 100644
index 0000000..a2a1fc0
--- /dev/null
+++ b/src/test/java/org/mockito/internal/AllInvocationsFinderTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.stubbing.Stubbing;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.internal.invocation.finder.AllInvocationsFinder.find;
+import static org.mockito.internal.invocation.finder.AllInvocationsFinder.findStubbings;
+
+public class AllInvocationsFinderTest extends TestBase {
+
+    private IMethods mockTwo;
+    private IMethods mockOne;
+
+    @Before
+    public void setup() {
+        mockOne = mock(IMethods.class);
+        mockTwo = mock(IMethods.class);
+    }
+
+    @Test
+    public void no_interactions() throws Exception {
+        //expect
+        assertTrue(find(asList(mockOne, mockTwo)).isEmpty());
+        assertTrue(findStubbings(asList(mockOne, mockTwo)).isEmpty());
+    }
+
+    @Test
+    public void provides_invocations_in_order() throws Exception {
+        //given
+        mockOne.simpleMethod(100);
+        mockTwo.simpleMethod(200);
+        mockOne.simpleMethod(300);
+
+        //when
+        List<Invocation> invocations = find(asList(mockOne, mockTwo));
+
+        //then
+        assertEquals(3, invocations.size());
+        assertArgumentEquals(100, invocations.get(0));
+        assertArgumentEquals(200, invocations.get(1));
+        assertArgumentEquals(300, invocations.get(2));
+    }
+
+    @Test
+    public void deduplicates_interactions_from_the_same_mock() throws Exception {
+        //given
+        mockOne.simpleMethod(100);
+
+        //when
+        List<Invocation> invocations = find(asList(mockOne, mockOne, mockOne));
+
+        //then
+        assertEquals(1, invocations.size());
+    }
+
+    @Test
+    public void provides_stubbings_in_order() throws Exception {
+        //given
+        mockOne.simpleMethod(50); //ignored, not a stubbing
+        when(mockOne.simpleMethod(100)).thenReturn("100");
+        when(mockOne.simpleMethod(200)).thenReturn("200");
+        when(mockTwo.simpleMethod(300)).thenReturn("300");
+
+        //when
+        List<Stubbing> stubbings = new ArrayList<Stubbing>(findStubbings(asList(mockOne, mockOne, mockTwo)));
+
+        //then
+        assertEquals(3, stubbings.size());
+        assertArgumentEquals(100, stubbings.get(0).getInvocation());
+        assertArgumentEquals(200, stubbings.get(1).getInvocation());
+        assertArgumentEquals(300, stubbings.get(2).getInvocation());
+    }
+
+    private void assertArgumentEquals(Object argumentValue, Invocation invocation) {
+        assertEquals(argumentValue, invocation.getArgument(0));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/InOrderImplTest.java b/src/test/java/org/mockito/internal/InOrderImplTest.java
new file mode 100644
index 0000000..0eb95ab
--- /dev/null
+++ b/src/test/java/org/mockito/internal/InOrderImplTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static java.util.Collections.singletonList;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+@SuppressWarnings("unchecked")
+public class InOrderImplTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @Test
+    public void shouldMarkVerifiedInOrder() throws Exception {
+        //given
+        InOrderImpl impl = new InOrderImpl(singletonList(mock));
+        Invocation i = new InvocationBuilder().toInvocation();
+        assertFalse(impl.isVerified(i));
+
+        //when
+        impl.markVerified(i);
+
+        //then
+        assertTrue(impl.isVerified(i));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/InvalidStateDetectionTest.java b/src/test/java/org/mockito/internal/InvalidStateDetectionTest.java
new file mode 100644
index 0000000..850b949
--- /dev/null
+++ b/src/test/java/org/mockito/internal/InvalidStateDetectionTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.StateMaster;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+/**
+ * invalid state happens if:
+ *
+ *    -unfinished stubbing
+ *    -unfinished doReturn()
+ *    -stubbing without actual method call
+ *    -verify without actual method call
+ *
+ * we should aim to detect invalid state in following scenarios:
+ *
+ *    -on method call on mock
+ *    -on verify
+ *    -on verifyZeroInteractions
+ *    -on verifyNoMoreInteractions
+ *    -on verify in order
+ *    -on stub
+ */
+@SuppressWarnings({"unchecked", "deprecation"})
+public class InvalidStateDetectionTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @After
+    public void resetState() {
+        super.resetState();
+    }
+
+    @Test
+    public void shouldDetectUnfinishedStubbing() {
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnMethodCallOnMock(), UnfinishedStubbingException.class);
+
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnStub(), UnfinishedStubbingException.class);
+
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnVerify(), UnfinishedStubbingException.class);
+
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnVerifyInOrder(), UnfinishedStubbingException.class);
+
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnVerifyZeroInteractions(), UnfinishedStubbingException.class);
+
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), UnfinishedStubbingException.class);
+
+        when(mock.simpleMethod());
+        detectsAndCleansUp(new OnDoAnswer(), UnfinishedStubbingException.class);
+    }
+
+    @Test
+    public void shouldDetectUnfinishedDoAnswerStubbing() {
+        doAnswer(null);
+        detectsAndCleansUp(new OnMethodCallOnMock(), UnfinishedStubbingException.class);
+
+        doAnswer(null);
+        detectsAndCleansUp(new OnStub(), UnfinishedStubbingException.class);
+
+        doAnswer(null);
+        detectsAndCleansUp(new OnVerify(), UnfinishedStubbingException.class);
+
+        doAnswer(null);
+        detectsAndCleansUp(new OnVerifyInOrder(), UnfinishedStubbingException.class);
+
+        doAnswer(null);
+        detectsAndCleansUp(new OnVerifyZeroInteractions(), UnfinishedStubbingException.class);
+
+        doAnswer(null);
+        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), UnfinishedStubbingException.class);
+
+        doAnswer(null);
+        detectsAndCleansUp(new OnDoAnswer(), UnfinishedStubbingException.class);
+    }
+
+    @Test
+    public void shouldDetectUnfinishedVerification() {
+        verify(mock);
+        detectsAndCleansUp(new OnStub(), UnfinishedVerificationException.class);
+
+        verify(mock);
+        detectsAndCleansUp(new OnVerify(), UnfinishedVerificationException.class);
+
+        verify(mock);
+        detectsAndCleansUp(new OnVerifyInOrder(), UnfinishedVerificationException.class);
+
+        verify(mock);
+        detectsAndCleansUp(new OnVerifyZeroInteractions(), UnfinishedVerificationException.class);
+
+        verify(mock);
+        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), UnfinishedVerificationException.class);
+
+        verify(mock);
+        detectsAndCleansUp(new OnDoAnswer(), UnfinishedVerificationException.class);
+    }
+
+    @Test
+    public void shouldDetectMisplacedArgumentMatcher() {
+        anyObject();
+        detectsAndCleansUp(new OnVerify(), InvalidUseOfMatchersException.class);
+
+        anyObject();
+        detectsAndCleansUp(new OnVerifyInOrder(), InvalidUseOfMatchersException.class);
+
+        anyObject();
+        detectsAndCleansUp(new OnVerifyZeroInteractions(), InvalidUseOfMatchersException.class);
+
+        anyObject();
+        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), InvalidUseOfMatchersException.class);
+
+        anyObject();
+        detectsAndCleansUp(new OnDoAnswer(), InvalidUseOfMatchersException.class);
+    }
+
+    @Test
+    public void shouldCorrectStateAfterDetectingUnfinishedStubbing() {
+        doThrow(new RuntimeException()).when(mock);
+
+        try {
+        	doThrow(new RuntimeException()).when(mock).oneArg(true);
+            fail();
+        } catch (UnfinishedStubbingException e) {}
+
+        doThrow(new RuntimeException()).when(mock).oneArg(true);
+        try {
+            mock.oneArg(true);
+            fail();
+        } catch (RuntimeException e) {}
+    }
+
+    @Test
+    public void shouldCorrectStateAfterDetectingUnfinishedVerification() {
+        mock.simpleMethod();
+        verify(mock);
+
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (UnfinishedVerificationException e) {}
+
+        verify(mock).simpleMethod();
+    }
+
+    private interface DetectsInvalidState {
+        void detect(IMethods mock);
+    }
+
+    private static class OnVerify implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            verify(mock);
+        }
+    }
+
+    private static class OnVerifyInOrder implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            inOrder(mock).verify(mock);
+        }
+    }
+
+    private static class OnVerifyZeroInteractions implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            verifyZeroInteractions(mock);
+        }
+    }
+
+    private static class OnVerifyNoMoreInteractions implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            verifyNoMoreInteractions(mock);
+        }
+    }
+
+    private static class OnDoAnswer implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            doAnswer(null);
+        }
+    }
+
+    private static class OnStub implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            when(mock);
+        }
+    }
+
+    private static class OnMethodCallOnMock implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            mock.simpleMethod();
+        }
+    }
+
+    private static class OnMockCreation implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            mock(IMethods.class);
+        }
+    }
+
+    private static class OnSpyCreation implements DetectsInvalidState {
+        public void detect(IMethods mock) {
+            spy(new Object());
+        }
+    }
+
+    private void detectsAndCleansUp(DetectsInvalidState detector, Class<?> expected) {
+        try {
+            detector.detect(mock);
+            fail("Should throw an exception");
+        } catch (Exception e) {
+            assertEquals(expected, e.getClass());
+        }
+        //Make sure state is cleaned up
+        new StateMaster().validate();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/ClassPathLoaderTest.java b/src/test/java/org/mockito/internal/configuration/ClassPathLoaderTest.java
new file mode 100644
index 0000000..e18eb21
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/ClassPathLoaderTest.java
@@ -0,0 +1,24 @@
+package org.mockito.internal.configuration;
+
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+public class ClassPathLoaderTest extends TestBase {
+
+    @Test
+    public void shouldReadConfigurationClassFromClassPath() {
+        ConfigurationAccess.getConfig().overrideDefaultAnswer(new Answer<Object>() {
+            public Object answer(InvocationOnMock invocation) {
+                return "foo";
+            }});
+
+        IMethods mock = mock(IMethods.class);
+        assertEquals("foo", mock.simpleMethod());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/ConfigurationAccess.java b/src/test/java/org/mockito/internal/configuration/ConfigurationAccess.java
new file mode 100644
index 0000000..a3367e6
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/ConfigurationAccess.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.configuration.MockitoConfiguration;
+
+public class ConfigurationAccess {
+
+    public static MockitoConfiguration getConfig() {
+        return (MockitoConfiguration) new GlobalConfiguration().getIt();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/GlobalConfigurationTest.java b/src/test/java/org/mockito/internal/configuration/GlobalConfigurationTest.java
new file mode 100644
index 0000000..5725670
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/GlobalConfigurationTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import net.bytebuddy.ByteBuddy;
+import org.assertj.core.api.Assertions;
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockitoutil.ClassLoaders;
+import org.objenesis.Objenesis;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GlobalConfigurationTest {
+    @Test
+    public void returns_mockito_configuration_annotation_engine_if_non_default() throws Exception {
+        ConfigurationAccess.getConfig().overrideAnnotationEngine(new CustomAnnotationEngine());
+        assertThat(new GlobalConfiguration().getAnnotationEngine()).isInstanceOf(CustomAnnotationEngine.class);
+        assertThat(new GlobalConfiguration().tryGetPluginAnnotationEngine()).isInstanceOf(CustomAnnotationEngine.class);
+    }
+
+    @Test
+    public void returns_mockito_annotation_engine_of_Plugins_if_no_MockitoConfiguration() throws Throwable {
+        ClassLoader anotherWorld = ClassLoaders.isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withCodeSourceUrlOf(Mockito.class, ByteBuddy.class, Objenesis.class)
+                .withPrivateCopyOf("org.mockito", "net.bytebuddy", "org.objenesis")
+                .withCodeSourceUrlOf(Assertions.class)
+                .withPrivateCopyOf("org.assertj")
+                .without("org.mockito.configuration.MockitoConfiguration")
+                .build();
+
+        ClassLoaders.using(anotherWorld).execute(new Runnable() {
+            @Override
+            public void run() {
+                assertThat(new GlobalConfiguration().getAnnotationEngine()).isInstanceOf(Plugins.getAnnotationEngine().getClass());
+                assertThat(new GlobalConfiguration().tryGetPluginAnnotationEngine()).isInstanceOf(Plugins.getAnnotationEngine().getClass());
+            }
+        });
+    }
+
+    @After
+    public void reset_annotation_engine() {
+        ConfigurationAccess.getConfig().overrideAnnotationEngine(null);
+    }
+
+    private static class CustomAnnotationEngine implements AnnotationEngine {
+        @Override public void process(Class<?> clazz, Object testInstance) { }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/MockInjectionTest.java b/src/test/java/org/mockito/internal/configuration/MockInjectionTest.java
new file mode 100644
index 0000000..4abb528
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/MockInjectionTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.internal.configuration.injection.MockInjection;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Observer;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+@SuppressWarnings("unchecked")
+public class MockInjectionTest {
+
+    private AnObjectWithConstructor withConstructor;
+    private AnObjectWithoutConstructor withoutConstructor;
+
+    @After
+    public void reset() throws Exception {
+        withConstructor = null;
+        withoutConstructor = null;
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void should_not_allow_null_on_field() {
+        MockInjection.onField((Field) null, this);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void should_not_allow_null_on_fields() {
+        MockInjection.onFields((Set<Field>) null, this);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void should_not_allow_null_on_instance_owning_the_field() throws Exception {
+        MockInjection.onField(field("withConstructor"), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void should_not_allow_null_on_mocks() throws Exception {
+        MockInjection.onField(field("withConstructor"), this).withMocks(null);
+    }
+
+
+    @Test
+    public void can_try_constructor_injection() throws Exception {
+        MockInjection.onField(field("withConstructor"), this).withMocks(oneSetMock()).tryConstructorInjection().apply();
+
+        assertThat(withConstructor.initializedWithConstructor).isEqualTo(true);
+    }
+
+    @Test
+    public void should_not_fail_if_constructor_injection_is_not_possible() throws Exception {
+        MockInjection.onField(field("withoutConstructor"), this).withMocks(otherKindOfMocks()).tryConstructorInjection().apply();
+
+        assertThat(withoutConstructor).isNull();
+    }
+
+    @Test
+    public void can_try_property_or_setter_injection() throws Exception {
+        MockInjection.onField(field("withoutConstructor"), this).withMocks(oneSetMock()).tryPropertyOrFieldInjection().apply();
+
+        assertThat(withoutConstructor.theSet).isNotNull();
+    }
+
+    @Test
+    public void should_not_fail_if_property_or_field_injection_is_not_possible() throws Exception {
+        MockInjection.onField(field("withoutConstructor"), this).withMocks(otherKindOfMocks()).tryPropertyOrFieldInjection().apply();
+
+        assertThat(withoutConstructor.theSet).isNull();
+    }
+
+    private Set oneSetMock() {
+        return Collections.singleton(mock(Set.class));
+    }
+
+    private Set otherKindOfMocks() {
+        return Collections.singleton(mock(Observer.class));
+    }
+
+    private Field field(String field) throws NoSuchFieldException {
+        return getClass().getDeclaredField(field);
+    }
+
+
+    public static class AnObjectWithConstructor {
+        public boolean initializedWithConstructor = false;
+        public AnObjectWithConstructor(Set<String> strings) {
+            initializedWithConstructor = true;
+        }
+    }
+
+    public static class AnObjectWithoutConstructor {
+        private Set<?> theSet;
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/injection/ConstructorInjectionTest.java b/src/test/java/org/mockito/internal/configuration/injection/ConstructorInjectionTest.java
new file mode 100644
index 0000000..335d2e4
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/injection/ConstructorInjectionTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Observer;
+import java.util.Set;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ConstructorInjectionTest {
+
+    @Mock private Observer observer;
+    private ArgConstructor whatever;
+
+    private ConstructorInjection underTest;
+
+    @Before
+    public void initialize_dependencies() {
+        underTest = new ConstructorInjection();
+    }
+
+    @Test
+    public void should_do_the_trick_of_instantiating() throws Exception {
+        boolean result = underTest.process(field("whatever"), this, newSetOf(observer));
+
+        assertTrue(result);
+        assertNotNull(whatever);
+    }
+
+    private Set<Object> newSetOf(Object item) {
+        HashSet<Object> mocks = new HashSet<Object>();
+        mocks.add(item);
+        return mocks;
+    }
+
+    private Field field(String fieldName) throws NoSuchFieldException {
+        return this.getClass().getDeclaredField(fieldName);
+    }
+
+    private static class ArgConstructor {
+        ArgConstructor(Observer observer) {}
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/injection/SimpleArgumentResolverTest.java b/src/test/java/org/mockito/internal/configuration/injection/SimpleArgumentResolverTest.java
new file mode 100644
index 0000000..4f3017d
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/injection/SimpleArgumentResolverTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+public class SimpleArgumentResolverTest {
+
+    @Test
+    public void should_return_object_matching_given_types() throws Exception {
+        ConstructorInjection.SimpleArgumentResolver resolver =
+                new ConstructorInjection.SimpleArgumentResolver(newSetOf(new HashSet<Long>(), new ByteArrayOutputStream(), new HashMap<String, String>()));
+
+        Object[] resolvedInstance = resolver.resolveTypeInstances(Set.class, Map.class, OutputStream.class);
+
+        assertEquals(3, resolvedInstance.length);
+        assertTrue(resolvedInstance[0] instanceof Set);
+        assertTrue(resolvedInstance[1] instanceof Map);
+        assertTrue(resolvedInstance[2] instanceof OutputStream);
+    }
+
+    @Test
+    public void should_return_null_when_match_is_not_possible_on_given_types() throws Exception {
+        ConstructorInjection.SimpleArgumentResolver resolver =
+                new ConstructorInjection.SimpleArgumentResolver(newSetOf(new HashSet<Float>(), new ByteArrayOutputStream()));
+
+        Object[] resolvedInstance = resolver.resolveTypeInstances(Set.class, Map.class, OutputStream.class);
+
+        assertEquals(3, resolvedInstance.length);
+        assertTrue(resolvedInstance[0] instanceof Set);
+        assertNull(resolvedInstance[1]);
+        assertTrue(resolvedInstance[2] instanceof OutputStream);
+    }
+
+    @Test
+    public void should_return_null_when_types_are_primitives() throws Exception {
+        ConstructorInjection.SimpleArgumentResolver resolver =
+                new ConstructorInjection.SimpleArgumentResolver(newSetOf(new HashMap<Integer, String>(), new TreeSet<Integer>()));
+
+        Object[] resolvedInstance = resolver.resolveTypeInstances(Set.class, Map.class, Boolean.class);
+
+        assertEquals(3, resolvedInstance.length);
+        assertTrue(resolvedInstance[0] instanceof Set);
+        assertTrue(resolvedInstance[1] instanceof Map);
+        assertNull(resolvedInstance[2]);
+    }
+
+    private Set<Object> newSetOf(Object... objects) {
+        return new HashSet<Object>(Arrays.asList(objects));
+    }
+
+
+}
diff --git a/src/test/java/org/mockito/internal/configuration/plugins/PluginFileReaderTest.java b/src/test/java/org/mockito/internal/configuration/plugins/PluginFileReaderTest.java
new file mode 100644
index 0000000..d047046
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/plugins/PluginFileReaderTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.plugins;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNull;
+
+public class PluginFileReaderTest extends TestBase {
+
+    PluginFileReader reader = new PluginFileReader();
+
+    @Test
+    public void no_class_in_resource() throws IOException {
+        //no class
+        assertNull(reader.readPluginClass(impl("")));
+        assertNull(reader.readPluginClass(impl("  ")));
+        assertNull(reader.readPluginClass(impl(" \n ")));
+
+        //commented out
+        assertNull(reader.readPluginClass(impl("#foo")));
+        assertNull(reader.readPluginClass(impl("  # foo  ")));
+        assertNull(reader.readPluginClass(impl("  # # # java.langString # ")));
+        assertNull(reader.readPluginClass(impl("  \n # foo \n # foo \n ")));
+    }
+
+    private InputStream impl(String s) {
+        return new ByteArrayInputStream(s.getBytes());
+    }
+
+    @Test
+    public void reads_class_name() throws IOException {
+        assertEquals("java.lang.String", reader.readPluginClass(impl("java.lang.String")));
+        assertEquals("x", reader.readPluginClass(impl("x")));
+        assertEquals("x y z", reader.readPluginClass(impl(" x y z ")));
+        assertEquals("foo.Foo", reader.readPluginClass(impl(" #my class\n  foo.Foo \n #other class ")));
+        assertEquals("foo.Foo", reader.readPluginClass(impl("foo.Foo  # cool class")));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/configuration/plugins/PluginFinderTest.java b/src/test/java/org/mockito/internal/configuration/plugins/PluginFinderTest.java
new file mode 100644
index 0000000..fc6d326
--- /dev/null
+++ b/src/test/java/org/mockito/internal/configuration/plugins/PluginFinderTest.java
@@ -0,0 +1,114 @@
+package org.mockito.internal.configuration.plugins;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.internal.util.io.IOUtil;
+import org.mockito.plugins.PluginSwitch;
+import org.mockitoutil.TestBase;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Collections;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+public class PluginFinderTest extends TestBase {
+
+    @Mock
+    PluginSwitch switcher;
+    @InjectMocks PluginFinder finder;
+    public @Rule TemporaryFolder tmp = new TemporaryFolder();
+
+    @Test public void empty_resources() {
+        assertNull(finder.findPluginClass(Collections.<URL>emptyList()));
+    }
+
+    @Test public void no_valid_impl() throws Exception {
+        File f = tmp.newFile();
+
+        //when
+        IOUtil.writeText("  \n  ", f);
+
+        //then
+        assertNull(finder.findPluginClass(asList(f.toURI().toURL())));
+    }
+
+    @Test public void single_implementation() throws Exception {
+        File f = tmp.newFile();
+        when(switcher.isEnabled("foo.Foo")).thenReturn(true);
+
+        //when
+        IOUtil.writeText("  foo.Foo  ", f);
+
+        //then
+        assertEquals("foo.Foo", finder.findPluginClass(asList(f.toURI().toURL())));
+    }
+
+    @Test public void single_implementation_disabled() throws Exception {
+        File f = tmp.newFile();
+        when(switcher.isEnabled("foo.Foo")).thenReturn(false);
+
+        //when
+        IOUtil.writeText("  foo.Foo  ", f);
+
+        //then
+        assertEquals(null, finder.findPluginClass(asList(f.toURI().toURL())));
+    }
+
+    @Test public void multiple_implementations_only_one_enabled() throws Exception {
+        File f1 = tmp.newFile(); File f2 = tmp.newFile();
+
+        when(switcher.isEnabled("Bar")).thenReturn(true);
+
+        //when
+        IOUtil.writeText("Foo", f1); IOUtil.writeText("Bar", f2);
+
+        //then
+        assertEquals("Bar", finder.findPluginClass(asList(f1.toURI().toURL(), f2.toURI().toURL())));
+    }
+
+    @Test public void multiple_implementations_only_one_useful() throws Exception {
+        File f1 = tmp.newFile(); File f2 = tmp.newFile();
+
+        when(switcher.isEnabled(anyString())).thenReturn(true);
+
+        //when
+        IOUtil.writeText("   ", f1); IOUtil.writeText("X", f2);
+
+        //then
+        assertEquals("X", finder.findPluginClass(asList(f1.toURI().toURL(), f2.toURI().toURL())));
+    }
+
+    @Test public void multiple_empty_implementations() throws Exception {
+        File f1 = tmp.newFile(); File f2 = tmp.newFile();
+
+        when(switcher.isEnabled(anyString())).thenReturn(true);
+
+        //when
+        IOUtil.writeText("   ", f1); IOUtil.writeText("\n", f2);
+
+        //then
+        assertEquals(null, finder.findPluginClass(asList(f1.toURI().toURL(), f2.toURI().toURL())));
+    }
+
+    @Test public void problems_loading_impl() throws Exception {
+        when(switcher.isEnabled(anyString())).thenThrow(new RuntimeException("Boo!"));
+
+        try {
+            //when
+            finder.findPluginClass(asList(new File("xxx").toURI().toURL()));
+            //then
+            fail();
+        } catch(Exception e) {
+            assertThat(e).hasMessageContaining("xxx");
+            e.getCause().getMessage().equals("Boo!");
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/DelegatingMethodTest.java b/src/test/java/org/mockito/internal/creation/DelegatingMethodTest.java
new file mode 100644
index 0000000..5f8b087
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/DelegatingMethodTest.java
@@ -0,0 +1,57 @@
+package org.mockito.internal.creation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.Method;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+public class DelegatingMethodTest extends TestBase {
+
+    private Method someMethod, otherMethod;
+    private DelegatingMethod delegatingMethod;
+
+    @Before
+    public void setup() throws Exception {
+        someMethod = Something.class.getMethod("someMethod", Object.class);
+        otherMethod = Something.class.getMethod("otherMethod", Object.class);
+        delegatingMethod = new DelegatingMethod(someMethod);
+    }
+
+    @Test
+    public void equals_should_return_false_when_not_equal() throws Exception {
+        DelegatingMethod notEqual = new DelegatingMethod(otherMethod);
+        assertFalse(delegatingMethod.equals(notEqual));
+    }
+
+    @Test
+    public void equals_should_return_true_when_equal() throws Exception {
+        DelegatingMethod equal = new DelegatingMethod(someMethod);
+        assertTrue(delegatingMethod.equals(equal));
+    }
+
+    @Test
+    public void equals_should_return_true_when_self() throws Exception {
+        assertTrue(delegatingMethod.equals(delegatingMethod));
+    }
+
+    @Test
+    public void equals_should_return_false_when_not_equal_to_method() throws Exception {
+        assertFalse(delegatingMethod.equals(otherMethod));
+    }
+
+    @Test
+    public void equals_should_return_true_when_equal_to_method() throws Exception {
+        assertTrue(delegatingMethod.equals(someMethod));
+    }
+
+    private interface Something {
+
+        Object someMethod(Object param);
+
+        Object otherMethod(Object param);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/MockSettingsImplTest.java b/src/test/java/org/mockito/internal/creation/MockSettingsImplTest.java
new file mode 100644
index 0000000..1854f08
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/MockSettingsImplTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.debugging.VerboseMockInvocationLogger;
+import org.mockito.listeners.InvocationListener;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MockSettingsImplTest extends TestBase {
+
+    private MockSettingsImpl<?> mockSettingsImpl = new MockSettingsImpl<Object>();
+
+    @Mock private InvocationListener invocationListener;
+
+    @Test(expected=MockitoException.class)
+    @SuppressWarnings("unchecked")
+    public void shouldNotAllowSettingNullInterface() {
+        mockSettingsImpl.extraInterfaces(List.class, null);
+    }
+
+    @Test(expected=MockitoException.class)
+    @SuppressWarnings("unchecked")
+    public void shouldNotAllowNonInterfaces() {
+        mockSettingsImpl.extraInterfaces(List.class, LinkedList.class);
+    }
+
+    @Test(expected=MockitoException.class)
+    @SuppressWarnings("unchecked")
+    public void shouldNotAllowUsingTheSameInterfaceAsExtra() {
+        mockSettingsImpl.extraInterfaces(List.class, LinkedList.class);
+    }
+
+    @Test(expected=MockitoException.class)
+    @SuppressWarnings("unchecked")
+    public void shouldNotAllowEmptyExtraInterfaces() {
+        mockSettingsImpl.extraInterfaces();
+    }
+
+    @Test(expected=MockitoException.class)
+    @SuppressWarnings("unchecked")
+    public void shouldNotAllowNullArrayOfExtraInterfaces() {
+        mockSettingsImpl.extraInterfaces((Class<?>[]) null);
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void shouldAllowMultipleInterfaces() {
+        //when
+        mockSettingsImpl.extraInterfaces(List.class, Set.class);
+
+        //then
+        assertEquals(2, mockSettingsImpl.getExtraInterfaces().size());
+        assertTrue(mockSettingsImpl.getExtraInterfaces().contains(List.class));
+        assertTrue(mockSettingsImpl.getExtraInterfaces().contains(Set.class));
+    }
+
+    @Test
+    public void shouldSetMockToBeSerializable() throws Exception {
+        //when
+        mockSettingsImpl.serializable();
+
+        //then
+        assertTrue(mockSettingsImpl.isSerializable());
+    }
+
+    @Test
+    public void shouldKnowIfIsSerializable() throws Exception {
+        //given
+        assertFalse(mockSettingsImpl.isSerializable());
+
+        //when
+        mockSettingsImpl.serializable();
+
+        //then
+        assertTrue(mockSettingsImpl.isSerializable());
+    }
+
+    @Test
+    public void shouldAddVerboseLoggingListener() {
+        //given
+        assertFalse(mockSettingsImpl.hasInvocationListeners());
+
+        //when
+        mockSettingsImpl.verboseLogging();
+
+        //then
+        assertThat(mockSettingsImpl.getInvocationListeners()).extracting("class").contains(VerboseMockInvocationLogger.class);
+    }
+
+    @Test
+    public void shouldAddVerboseLoggingListenerOnlyOnce() {
+        //given
+        assertFalse(mockSettingsImpl.hasInvocationListeners());
+
+        //when
+        mockSettingsImpl.verboseLogging().verboseLogging();
+
+        //then
+        Assertions.assertThat(mockSettingsImpl.getInvocationListeners()).hasSize(1);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowNullListener() {
+        mockSettingsImpl.invocationListeners((InvocationListener[])null);
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void shouldAddInvocationListener() {
+        //given
+        assertFalse(mockSettingsImpl.hasInvocationListeners());
+
+        //when
+        mockSettingsImpl.invocationListeners(invocationListener);
+
+        //then
+        Assertions.assertThat(mockSettingsImpl.getInvocationListeners()).contains(invocationListener);
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void canAddDuplicateInvocationListeners_ItsNotOurBusinessThere() {
+        //given
+        assertFalse(mockSettingsImpl.hasInvocationListeners());
+
+        //when
+        mockSettingsImpl.invocationListeners(invocationListener, invocationListener).invocationListeners(invocationListener);
+
+        //then
+        Assertions.assertThat(mockSettingsImpl.getInvocationListeners()).containsSequence(invocationListener, invocationListener, invocationListener);
+    }
+
+    @Test
+    public void shouldReportErrorWhenAddingNoInvocationListeners() throws Exception {
+        try {
+            mockSettingsImpl.invocationListeners();
+            fail();
+        } catch (Exception e) {
+            Assertions.assertThat(e.getMessage()).contains("at least one listener");
+        }
+    }
+
+    @Test
+    public void shouldReportErrorWhenAddingANullInvocationListener() throws Exception {
+        try {
+            mockSettingsImpl.invocationListeners(invocationListener, null);
+            fail();
+        } catch (Exception e) {
+            Assertions.assertThat(e.getMessage()).contains("does not accept null");
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/bytebuddy/AbstractByteBuddyMockMakerTest.java b/src/test/java/org/mockito/internal/creation/bytebuddy/AbstractByteBuddyMockMakerTest.java
new file mode 100644
index 0000000..02955ab
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/bytebuddy/AbstractByteBuddyMockMakerTest.java
@@ -0,0 +1,204 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.ByteBuddy;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.handler.MockHandlerImpl;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.SerializableMode;
+import org.mockito.plugins.MockMaker;
+import org.mockito.stubbing.Answer;
+import org.mockitoutil.ClassLoaders;
+import org.mockitoutil.SimpleSerializationUtil;
+import org.objenesis.ObjenesisStd;
+
+import java.io.Serializable;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockitoutil.ClassLoaders.coverageTool;
+
+public abstract class AbstractByteBuddyMockMakerTest<MM extends MockMaker> {
+
+    protected final MM mockMaker;
+
+    public AbstractByteBuddyMockMakerTest(MM mockMaker) {
+        this.mockMaker = mockMaker;
+    }
+
+    protected abstract Class<?> mockTypeOf(Class<?> type);
+
+    @Test
+    public void should_create_mock_from_interface() throws Exception {
+        SomeInterface proxy = mockMaker.createMock(settingsFor(SomeInterface.class), dummyH());
+
+        Class<?> superClass = proxy.getClass().getSuperclass();
+        assertThat(superClass).isEqualTo(Object.class);
+    }
+
+
+    @Test
+    public void should_create_mock_from_class() throws Exception {
+        ClassWithoutConstructor proxy = mockMaker.createMock(settingsFor(ClassWithoutConstructor.class), dummyH());
+
+        Class<?> superClass = mockTypeOf(proxy.getClass());
+        assertThat(superClass).isEqualTo(ClassWithoutConstructor.class);
+    }
+
+    @Test
+    public void should_create_mock_from_class_even_when_constructor_is_dodgy() throws Exception {
+        try {
+            new ClassWithDodgyConstructor();
+            fail();
+        } catch (Exception expected) {}
+
+        ClassWithDodgyConstructor mock = mockMaker.createMock(settingsFor(ClassWithDodgyConstructor.class), dummyH());
+        assertThat(mock).isNotNull();
+    }
+
+    @Test
+    public void should_mocks_have_different_interceptors() throws Exception {
+        SomeClass mockOne = mockMaker.createMock(settingsFor(SomeClass.class), dummyH());
+        SomeClass mockTwo = mockMaker.createMock(settingsFor(SomeClass.class), dummyH());
+
+        MockHandler handlerOne = mockMaker.getHandler(mockOne);
+        MockHandler handlerTwo = mockMaker.getHandler(mockTwo);
+
+
+        assertThat(handlerOne).isNotSameAs(handlerTwo);
+    }
+
+    @Test
+    public void should_use_ancillary_Types() {
+        SomeClass mock = mockMaker.createMock(settingsFor(SomeClass.class, SomeInterface.class), dummyH());
+
+        assertThat(mock).isInstanceOf(SomeInterface.class);
+    }
+
+    @Test
+    public void should_create_class_by_constructor() {
+        OtherClass mock = mockMaker.createMock(settingsWithConstructorFor(OtherClass.class), dummyH());
+        assertThat(mock).isNotNull();
+    }
+
+    @Test
+    public void should_allow_serialization() throws Exception {
+        SerializableClass proxy = mockMaker.createMock(serializableSettingsFor(SerializableClass.class, SerializableMode.BASIC), dummyH());
+
+        SerializableClass serialized = SimpleSerializationUtil.serializeAndBack(proxy);
+        assertThat(serialized).isNotNull();
+
+        MockHandler handlerOne = mockMaker.getHandler(proxy);
+        MockHandler handlerTwo = mockMaker.getHandler(serialized);
+
+        assertThat(handlerOne).isNotSameAs(handlerTwo);
+    }
+
+    @Test
+    public void should_create_mock_from_class_with_super_call_to_final_method() throws Exception {
+        MockCreationSettings<CallingSuperMethodClass> settings = settingsWithSuperCall(CallingSuperMethodClass.class);
+        SampleClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<CallingSuperMethodClass>(settings));
+        assertThat(proxy.foo()).isEqualTo("foo");
+    }
+
+    @Test
+    public void should_reset_mock_and_set_new_handler() throws Throwable {
+        MockCreationSettings<SampleClass> settings = settingsWithSuperCall(SampleClass.class);
+        SampleClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<SampleClass>(settings));
+
+        MockHandler handler = new MockHandlerImpl<SampleClass>(settings);
+        mockMaker.resetMock(proxy, handler, settings);
+        assertThat(mockMaker.getHandler(proxy)).isSameAs(handler);
+    }
+
+    class SomeClass {}
+    interface SomeInterface {}
+    static class OtherClass {}
+    static class SerializableClass implements Serializable {}
+
+    private class ClassWithoutConstructor {}
+
+    private class ClassWithDodgyConstructor {
+        public ClassWithDodgyConstructor() {
+            throw new RuntimeException();
+        }
+    }
+
+    @Test
+    public void instantiate_fine_when_objenesis_on_the_classpath() throws Exception {
+        // given
+        ClassLoader classpath_with_objenesis = ClassLoaders.excludingClassLoader()
+                .withCodeSourceUrlOf(Mockito.class, ByteBuddy.class, ObjenesisStd.class)
+                .withCodeSourceUrlOf(coverageTool())
+                .build();
+
+        Class<?> mock_maker_class_loaded_fine_until = Class.forName(
+                "org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker",
+                true,
+                classpath_with_objenesis
+        );
+
+        // when
+        mock_maker_class_loaded_fine_until.newInstance();
+
+        // then everything went fine
+    }
+
+    private static <T> MockCreationSettings<T> settingsFor(Class<T> type, Class<?>... extraInterfaces) {
+        MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
+        mockSettings.setTypeToMock(type);
+        if(extraInterfaces.length > 0) mockSettings.extraInterfaces(extraInterfaces);
+        return mockSettings;
+    }
+
+    private static <T> MockCreationSettings<T> serializableSettingsFor(Class<T> type, SerializableMode serializableMode) {
+        MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
+        mockSettings.serializable(serializableMode);
+        mockSettings.setTypeToMock(type);
+        return mockSettings;
+    }
+
+    private static <T> MockCreationSettings<T> settingsWithConstructorFor(Class<T> type) {
+        MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
+        mockSettings.setTypeToMock(type);
+        return mockSettings;
+    }
+
+    private static <T> MockCreationSettings<T> settingsWithSuperCall(Class<T> type) {
+        MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
+        mockSettings.setTypeToMock(type);
+        mockSettings.defaultAnswer(new CallsRealMethods());
+        return mockSettings;
+    }
+
+    private static MockHandler dummyH() {
+        return new DummyMockHandler();
+    }
+
+    private static class DummyMockHandler implements InternalMockHandler<Object> {
+        public Object handle(Invocation invocation) throws Throwable { return null; }
+        public MockCreationSettings<Object> getMockSettings() { return null; }
+        public InvocationContainer getInvocationContainer() { return null; }
+        public void setAnswersForStubbing(List<Answer<?>> list) { }
+    }
+
+    private static class SampleClass {
+        public String foo() {
+            return "foo";
+        }
+    }
+
+    private static class CallingSuperMethodClass extends SampleClass {
+        @Override
+        public String foo() {
+            return super.foo();
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMakerTest.java b/src/test/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMakerTest.java
new file mode 100644
index 0000000..d03d0b2
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMakerTest.java
@@ -0,0 +1,37 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.handler.MockHandlerImpl;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.verify;
+
+public class ByteBuddyMockMakerTest extends TestBase {
+
+    @InjectMocks
+    private ByteBuddyMockMaker mockMaker = new ByteBuddyMockMaker();
+
+    @Mock
+    private ClassCreatingMockMaker delegate;
+
+    @Test
+    public void should_delegate_call() {
+        CreationSettings<Object> creationSettings = new CreationSettings<Object>();
+        MockHandlerImpl<Object> handler = new MockHandlerImpl<Object>(creationSettings);
+
+        mockMaker.createMockType(creationSettings);
+        mockMaker.createMock(creationSettings, handler);
+        mockMaker.getHandler(this);
+        mockMaker.isTypeMockable(Object.class);
+        mockMaker.resetMock(this, handler, creationSettings);
+
+        verify(delegate).createMock(creationSettings, handler);
+        verify(delegate).createMockType(creationSettings);
+        verify(delegate).getHandler(this);
+        verify(delegate).isTypeMockable(Object.class);
+        verify(delegate).resetMock(this, handler, creationSettings);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java b/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java
new file mode 100644
index 0000000..ee36f6d
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java
@@ -0,0 +1,315 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.ClassFileVersion;
+import net.bytebuddy.description.modifier.Visibility;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.implementation.StubMethod;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.handler.MockHandlerImpl;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.util.collections.Sets;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.SerializableMode;
+import org.mockito.plugins.MockMaker;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Observable;
+import java.util.Observer;
+import java.util.regex.Pattern;
+
+import static net.bytebuddy.ClassFileVersion.JAVA_V8;
+import static net.bytebuddy.ClassFileVersion.JAVA_V9;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.junit.Assume.assumeTrue;
+
+public class InlineByteBuddyMockMakerTest extends AbstractByteBuddyMockMakerTest<InlineByteBuddyMockMaker> {
+
+    public InlineByteBuddyMockMakerTest() {
+        super(new InlineByteBuddyMockMaker());
+    }
+
+    @Override
+    protected Class<?> mockTypeOf(Class<?> type) {
+        return type;
+    }
+
+    @Test
+    public void should_create_mock_from_final_class() throws Exception {
+        MockCreationSettings<FinalClass> settings = settingsFor(FinalClass.class);
+        FinalClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<FinalClass>(settings));
+        assertThat(proxy.foo()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_create_mock_from_final_class_in_the_JDK() throws Exception {
+        assumeTrue(ClassFileVersion.ofThisVm().isLessThan(JAVA_V9)); // Change when ByteBuddy has ASM6 - see #788
+
+        MockCreationSettings<Pattern> settings = settingsFor(Pattern.class);
+        Pattern proxy = mockMaker.createMock(settings, new MockHandlerImpl<Pattern>(settings));
+        assertThat(proxy.pattern()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_create_mock_from_abstract_class_with_final_method() throws Exception {
+        MockCreationSettings<FinalMethodAbstractType> settings = settingsFor(FinalMethodAbstractType.class);
+        FinalMethodAbstractType proxy = mockMaker.createMock(settings, new MockHandlerImpl<FinalMethodAbstractType>(settings));
+        assertThat(proxy.foo()).isEqualTo("bar");
+        assertThat(proxy.bar()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_create_mock_from_final_class_with_interface_methods() throws Exception {
+        MockCreationSettings<FinalMethod> settings = settingsFor(FinalMethod.class, SampleInterface.class);
+        FinalMethod proxy = mockMaker.createMock(settings, new MockHandlerImpl<FinalMethod>(settings));
+        assertThat(proxy.foo()).isEqualTo("bar");
+        assertThat(((SampleInterface) proxy).bar()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_create_mock_from_hashmap() throws Exception {
+        MockCreationSettings<HashMap> settings = settingsFor(HashMap.class);
+        HashMap proxy = mockMaker.createMock(settings, new MockHandlerImpl<HashMap>(settings));
+        assertThat(proxy.get(null)).isEqualTo("bar");
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void should_throw_exception_redefining_unmodifiable_class() {
+        MockCreationSettings settings = settingsFor(int.class);
+        try {
+            mockMaker.createMock(settings, new MockHandlerImpl(settings));
+            fail("Expected a MockitoException");
+        } catch (MockitoException e) {
+            e.printStackTrace();
+            assertThat(e).hasMessageContaining("Could not modify all classes");
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void should_throw_exception_redefining_array() {
+        int[] array = new int[5];
+        MockCreationSettings<? extends int[]> settings = settingsFor(array.getClass());
+        try {
+            mockMaker.createMock(settings, new MockHandlerImpl(settings));
+            fail("Expected a MockitoException");
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("Arrays cannot be mocked");
+        }
+    }
+
+    @Test
+    public void should_create_mock_from_enum() throws Exception {
+        MockCreationSettings<EnumClass> settings = settingsFor(EnumClass.class);
+        EnumClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<EnumClass>(settings));
+        assertThat(proxy.foo()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_fail_at_creating_a_mock_of_a_final_class_with_explicit_serialization() throws Exception {
+        MockCreationSettings<FinalClass> settings = new CreationSettings<FinalClass>()
+                .setTypeToMock(FinalClass.class)
+                .setSerializableMode(SerializableMode.BASIC);
+
+        try {
+            mockMaker.createMock(settings, new MockHandlerImpl<FinalClass>(settings));
+            fail("Expected a MockitoException");
+        } catch (MockitoException e) {
+            assertThat(e)
+                    .hasMessageContaining("Unsupported settings")
+                    .hasMessageContaining("serialization")
+                    .hasMessageContaining("extra interfaces");
+        }
+    }
+
+    @Test
+    public void should_fail_at_creating_a_mock_of_a_final_class_with_extra_interfaces() throws Exception {
+        MockCreationSettings<FinalClass> settings = new CreationSettings<FinalClass>()
+                .setTypeToMock(FinalClass.class)
+                .setExtraInterfaces(Sets.<Class<?>>newSet(List.class));
+
+        try {
+            mockMaker.createMock(settings, new MockHandlerImpl<FinalClass>(settings));
+            fail("Expected a MockitoException");
+        } catch (MockitoException e) {
+            assertThat(e)
+                    .hasMessageContaining("Unsupported settings")
+                    .hasMessageContaining("serialization")
+                    .hasMessageContaining("extra interfaces");
+        }
+    }
+
+    @Test
+    public void should_remove_recursive_self_call_from_stack_trace() throws Exception {
+        StackTraceElement[] stack = new StackTraceElement[]{
+                new StackTraceElement("foo", "", "", -1),
+                new StackTraceElement(SampleInterface.class.getName(), "", "", -1),
+                new StackTraceElement("qux", "", "", -1),
+                new StackTraceElement("bar", "", "", -1),
+                new StackTraceElement("baz", "", "", -1)
+        };
+
+        Throwable throwable = new Throwable();
+        throwable.setStackTrace(stack);
+        throwable = InlineByteBuddyMockMaker.hideRecursiveCall(throwable, 2, SampleInterface.class);
+
+        assertThat(throwable.getStackTrace()).isEqualTo(new StackTraceElement[]{
+                new StackTraceElement("foo", "", "", -1),
+                new StackTraceElement("bar", "", "", -1),
+                new StackTraceElement("baz", "", "", -1)
+        });
+    }
+
+    @Test
+    public void should_handle_missing_or_inconsistent_stack_trace() throws Exception {
+        Throwable throwable = new Throwable();
+        throwable.setStackTrace(new StackTraceElement[0]);
+        assertThat(InlineByteBuddyMockMaker.hideRecursiveCall(throwable, 0, SampleInterface.class)).isSameAs(throwable);
+    }
+
+    @Test
+    public void should_provide_reason_for_wrapper_class() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(Integer.class);
+        assertThat(mockable.nonMockableReason()).isEqualTo("Cannot mock wrapper types, String.class or Class.class");
+    }
+
+    @Test
+    public void should_provide_reason_for_vm_unsupported() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(int[].class);
+        assertThat(mockable.nonMockableReason()).isEqualTo("VM does not not support modification of given type");
+    }
+
+    @Test
+    public void is_type_mockable_excludes_String() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(String.class);
+        assertThat(mockable.mockable()).isFalse();
+        assertThat(mockable.nonMockableReason()).contains("Cannot mock wrapper types, String.class or Class.class");
+    }
+
+    @Test
+    public void is_type_mockable_excludes_Class() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(Class.class);
+        assertThat(mockable.mockable()).isFalse();
+        assertThat(mockable.nonMockableReason()).contains("Cannot mock wrapper types, String.class or Class.class");
+    }
+
+    @Test
+    public void is_type_mockable_excludes_primitive_classes() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(int.class);
+        assertThat(mockable.mockable()).isFalse();
+        assertThat(mockable.nonMockableReason()).contains("primitive");
+    }
+
+    @Test
+    public void is_type_mockable_allows_anonymous() {
+        Observer anonymous = new Observer() {
+            @Override
+            public void update(Observable o, Object arg) {
+            }
+        };
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(anonymous.getClass());
+        assertThat(mockable.mockable()).isTrue();
+        assertThat(mockable.nonMockableReason()).contains("");
+    }
+
+    @Test
+    public void is_type_mockable_give_empty_reason_if_type_is_mockable() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(SomeClass.class);
+        assertThat(mockable.mockable()).isTrue();
+        assertThat(mockable.nonMockableReason()).isEqualTo("");
+    }
+
+    @Test
+    public void is_type_mockable_give_allow_final_mockable_from_JDK() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(Pattern.class);
+        assertThat(mockable.mockable()).isTrue();
+        assertThat(mockable.nonMockableReason()).isEqualTo("");
+    }
+
+    @Test
+    public void test_parameters_retention() throws Exception {
+        assumeTrue(ClassFileVersion.ofThisVm().isAtLeast(JAVA_V8));
+        assumeTrue(ClassFileVersion.ofThisVm().isLessThan(JAVA_V9)); // Change when ByteBuddy has ASM6 - see #788
+
+        Class<?> typeWithParameters = new ByteBuddy()
+                .subclass(Object.class)
+                .defineMethod("foo", void.class, Visibility.PUBLIC)
+                .withParameter(String.class, "bar")
+                .intercept(StubMethod.INSTANCE)
+                .make()
+                .load(null)
+                .getLoaded();
+
+        MockCreationSettings<?> settings = settingsFor(typeWithParameters);
+        @SuppressWarnings("unchecked")
+        Object proxy = mockMaker.createMock(settings, new MockHandlerImpl(settings));
+
+        assertThat(proxy.getClass()).isEqualTo(typeWithParameters);
+        assertThat(new TypeDescription.ForLoadedType(typeWithParameters).getDeclaredMethods().filter(named("foo"))
+                .getOnly().getParameters().getOnly().getName()).isEqualTo("bar");
+    }
+
+    private static <T> MockCreationSettings<T> settingsFor(Class<T> type, Class<?>... extraInterfaces) {
+        MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
+        mockSettings.setTypeToMock(type);
+        mockSettings.defaultAnswer(new Returns("bar"));
+        if (extraInterfaces.length > 0) mockSettings.extraInterfaces(extraInterfaces);
+        return mockSettings;
+    }
+
+    @Test
+    public void testMockDispatcherIsRelocated() throws Exception {
+        assertThat(InlineByteBuddyMockMaker.class.getClassLoader().getResource("org/mockito/internal/creation/bytebuddy/MockMethodDispatcher.raw")).isNotNull();
+    }
+
+    private static final class FinalClass {
+
+        public String foo() {
+            return "foo";
+        }
+    }
+
+    private enum EnumClass {
+
+        INSTANCE;
+
+        public String foo() {
+            return "foo";
+        }
+    }
+
+    private abstract static class FinalMethodAbstractType {
+
+        public final String foo() {
+            return "foo";
+        }
+
+        public abstract String bar();
+    }
+
+    private static class FinalMethod {
+
+        public final String foo() {
+            return "foo";
+        }
+    }
+
+    private static class NonFinalMethod {
+
+        public String foo() {
+            return "foo";
+        }
+    }
+
+    private interface SampleInterface {
+
+        String bar();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMakerTest.java b/src/test/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMakerTest.java
new file mode 100644
index 0000000..9f4e4a6
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMakerTest.java
@@ -0,0 +1,53 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import org.junit.Test;
+import org.mockito.plugins.MockMaker;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SubclassByteBuddyMockMakerTest extends AbstractByteBuddyMockMakerTest<SubclassByteBuddyMockMaker> {
+
+    public SubclassByteBuddyMockMakerTest() {
+        super(new SubclassByteBuddyMockMaker());
+    }
+
+    @Test
+    public void is_type_mockable_excludes_primitive_wrapper_classes() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(Integer.class);
+        assertThat(mockable.mockable()).isFalse();
+        assertThat(mockable.nonMockableReason()).contains("final");
+    }
+
+    @Test
+    public void is_type_mockable_excludes_primitive_classes() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(int.class);
+        assertThat(mockable.mockable()).isFalse();
+        assertThat(mockable.nonMockableReason()).contains("primitive");
+    }
+
+    @Test
+    public void is_type_mockable_allow_anonymous() {
+        Observer anonymous = new Observer() {
+            @Override public void update(Observable o, Object arg) { }
+        };
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(anonymous.getClass());
+        assertThat(mockable.mockable()).isTrue();
+        assertThat(mockable.nonMockableReason()).contains("");
+    }
+
+    @Test
+    public void is_type_mockable_give_empty_reason_if_type_is_mockable() {
+        MockMaker.TypeMockability mockable = mockMaker.isTypeMockable(SomeClass.class);
+        assertThat(mockable.mockable()).isTrue();
+        assertThat(mockable.nonMockableReason()).isEqualTo("");
+    }
+
+
+    @Override
+    protected Class<?> mockTypeOf(Class<?> type) {
+        return type.getSuperclass();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/bytebuddy/TypeCachingMockBytecodeGeneratorTest.java b/src/test/java/org/mockito/internal/creation/bytebuddy/TypeCachingMockBytecodeGeneratorTest.java
new file mode 100644
index 0000000..f431fd1
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/bytebuddy/TypeCachingMockBytecodeGeneratorTest.java
@@ -0,0 +1,155 @@
+package org.mockito.internal.creation.bytebuddy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.mock.SerializableMode;
+import org.mockitoutil.VmArgAssumptions;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.WeakHashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.creation.bytebuddy.MockFeatures.withMockFeatures;
+import static org.mockitoutil.ClassLoaders.inMemoryClassLoader;
+import static org.mockitoutil.SimpleClassGenerator.makeMarkerInterface;
+
+public class TypeCachingMockBytecodeGeneratorTest {
+
+    @Before
+    public void ensure_disable_gc_is_activated() throws Exception {
+        VmArgAssumptions.assumeVmArgNotPresent("-XX:+DisableExplicitGC");
+    }
+
+    @Test
+    public void ensure_cache_is_cleared_if_no_reference_to_classloader_and_classes() throws Exception {
+        // given
+        ClassLoader classloader_with_life_shorter_than_cache = inMemoryClassLoader()
+                .withClassDefinition("foo.Bar", makeMarkerInterface("foo.Bar"))
+                .build();
+
+        TypeCachingBytecodeGenerator cachingMockBytecodeGenerator = new TypeCachingBytecodeGenerator(new SubclassBytecodeGenerator(), true);
+
+        Class<?> the_mock_type = cachingMockBytecodeGenerator.mockClass(withMockFeatures(
+                classloader_with_life_shorter_than_cache.loadClass("foo.Bar"),
+                Collections.<Class<?>>emptySet(),
+                SerializableMode.NONE
+        ));
+
+        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
+        Reference<Object> typeReference = new PhantomReference<Object>(the_mock_type, referenceQueue);
+
+        // when
+        classloader_with_life_shorter_than_cache = is_no_more_referenced();
+        the_mock_type = is_no_more_referenced();
+
+        System.gc();
+        ensure_gc_happened();
+
+        // then
+        assertThat(referenceQueue.poll()).isEqualTo(typeReference);
+    }
+
+    @Test
+    public void ensure_cache_returns_same_instance() throws Exception {
+        // given
+        ClassLoader classloader_with_life_shorter_than_cache = inMemoryClassLoader()
+                .withClassDefinition("foo.Bar", makeMarkerInterface("foo.Bar"))
+                .build();
+
+        TypeCachingBytecodeGenerator cachingMockBytecodeGenerator = new TypeCachingBytecodeGenerator(new SubclassBytecodeGenerator(), true);
+        Class<?> the_mock_type = cachingMockBytecodeGenerator.mockClass(withMockFeatures(
+                        classloader_with_life_shorter_than_cache.loadClass("foo.Bar"),
+                        Collections.<Class<?>>emptySet(),
+                        SerializableMode.NONE
+                ));
+
+        Class<?> other_mock_type = cachingMockBytecodeGenerator.mockClass(withMockFeatures(
+                classloader_with_life_shorter_than_cache.loadClass("foo.Bar"),
+                Collections.<Class<?>>emptySet(),
+                SerializableMode.NONE
+        ));
+
+        assertThat(other_mock_type).isSameAs(the_mock_type);
+
+        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
+        Reference<Object> typeReference = new PhantomReference<Object>(the_mock_type, referenceQueue);
+
+        // when
+        classloader_with_life_shorter_than_cache = is_no_more_referenced();
+        the_mock_type = is_no_more_referenced();
+        other_mock_type = is_no_more_referenced();
+
+        System.gc();
+        ensure_gc_happened();
+
+        // then
+        assertThat(referenceQueue.poll()).isEqualTo(typeReference);
+    }
+
+    @Test
+    public void ensure_cache_returns_different_instance_serializableMode() throws Exception {
+        // given
+        ClassLoader classloader_with_life_shorter_than_cache = inMemoryClassLoader()
+                .withClassDefinition("foo.Bar", makeMarkerInterface("foo.Bar"))
+                .build();
+
+        TypeCachingBytecodeGenerator cachingMockBytecodeGenerator = new TypeCachingBytecodeGenerator(new SubclassBytecodeGenerator(), true);
+        Class<?> the_mock_type = cachingMockBytecodeGenerator.mockClass(withMockFeatures(
+                classloader_with_life_shorter_than_cache.loadClass("foo.Bar"),
+                Collections.<Class<?>>emptySet(),
+                SerializableMode.NONE
+        ));
+
+        Class<?> other_mock_type = cachingMockBytecodeGenerator.mockClass(withMockFeatures(
+                classloader_with_life_shorter_than_cache.loadClass("foo.Bar"),
+                Collections.<Class<?>>emptySet(),
+                SerializableMode.BASIC
+        ));
+
+        assertThat(other_mock_type).isNotSameAs(the_mock_type);
+    }
+
+    @Test
+    public void validate_simple_code_idea_where_weakhashmap_with_classloader_as_key_get_GCed_when_no_more_references() throws Exception {
+        // given
+        WeakHashMap<ClassLoader, Object> cache = new WeakHashMap<ClassLoader, Object>();
+        ClassLoader short_lived_classloader = inMemoryClassLoader()
+                .withClassDefinition("foo.Bar", makeMarkerInterface("foo.Bar"))
+                .build();
+
+        cache.put(short_lived_classloader, new HoldingAReference(new WeakReference<Class<?>>(short_lived_classloader.loadClass("foo.Bar"))));
+
+        assertThat(cache).hasSize(1);
+
+        // when
+        short_lived_classloader = is_no_more_referenced();
+
+        System.gc();
+        ensure_gc_happened();
+
+        // then
+        assertThat(cache).isEmpty();
+    }
+
+    static class HoldingAReference {
+        final WeakReference<Class<?>> a;
+
+        HoldingAReference(WeakReference<Class<?>> a) {
+            this.a = a;
+        }
+    }
+
+
+    private static <T> T is_no_more_referenced() {
+        return null;
+    }
+
+    private static void ensure_gc_happened() throws InterruptedException {
+        // wait in order to make sure the GC happened
+        Thread.sleep(500);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/creation/instance/ConstructorInstantiatorTest.java b/src/test/java/org/mockito/internal/creation/instance/ConstructorInstantiatorTest.java
new file mode 100644
index 0000000..b669fa0
--- /dev/null
+++ b/src/test/java/org/mockito/internal/creation/instance/ConstructorInstantiatorTest.java
@@ -0,0 +1,52 @@
+package org.mockito.internal.creation.instance;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class ConstructorInstantiatorTest extends TestBase {
+
+    static class SomeClass {
+
+    }
+
+    class SomeInnerClass {
+
+    }
+
+    class ChildOfThis extends ConstructorInstantiatorTest {
+
+    }
+
+    static class SomeClass2 {
+
+        SomeClass2(String x) {
+        }
+    }
+
+    @Test
+    public void creates_instances() {
+        assertEquals(new ConstructorInstantiator(null).newInstance(SomeClass.class).getClass(), SomeClass.class);
+    }
+
+    @Test
+    public void creates_instances_of_inner_classes() {
+        assertEquals(new ConstructorInstantiator(this).newInstance(SomeInnerClass.class).getClass(), SomeInnerClass.class);
+        assertEquals(new ConstructorInstantiator(new ChildOfThis()).newInstance(SomeInnerClass.class).getClass(), SomeInnerClass.class);
+    }
+
+    @Test
+    public void explains_when_constructor_cannot_be_found() {
+        try {
+            new ConstructorInstantiator(null).newInstance(SomeClass2.class);
+            fail();
+        } catch (InstantiationException e) {
+            assertThat(e).hasMessageContaining("Unable to create instance of 'SomeClass2'.\n" +
+                    "Please ensure it has 0-arg constructor which invokes cleanly.");
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/debugging/LoggingListenerTest.java b/src/test/java/org/mockito/internal/debugging/LoggingListenerTest.java
new file mode 100644
index 0000000..870579a
--- /dev/null
+++ b/src/test/java/org/mockito/internal/debugging/LoggingListenerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+
+import org.junit.Test;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class LoggingListenerTest extends TestBase {
+
+    @Test
+    public void may_not_have_any_information() {
+        //given
+        LoggingListener listener = new LoggingListener(true);
+
+        //expect
+        assertEquals("", listener.getStubbingInfo());
+    }
+
+    @Test
+    public void informs_about_unused_stubs() {
+        //given
+        LoggingListener listener = new LoggingListener(false);
+
+        //when
+        listener.foundUnusedStub(invocationAt("at com.FooTest:30"));
+        listener.foundUnusedStub(invocationAt("at com.FooTest:32"));
+
+        //then
+        assertEquals(
+            "[Mockito] Additional stubbing information (see javadoc for StubbingInfo class):\n" +
+            "[Mockito]\n" +
+            "[Mockito] Unused stubbing (perhaps can be removed from the test?):\n" +
+            "[Mockito]\n" +
+            "[Mockito] 1. at com.FooTest:30\n" +
+            "[Mockito] 2. at com.FooTest:32", listener.getStubbingInfo());
+    }
+
+    @Test
+    public void calculates_indexes_for_clean_output() {
+        assertEquals(1, LoggingListener.indexOfNextPair(0));
+        assertEquals(2, LoggingListener.indexOfNextPair(2));
+        assertEquals(3, LoggingListener.indexOfNextPair(4));
+        assertEquals(4, LoggingListener.indexOfNextPair(6));
+    }
+
+    @Test
+    public void informs_about_unused_stubs_due_arg_mismatch() {
+        //given
+        LoggingListener listener = new LoggingListener(false);
+
+        //when
+        listener.foundStubCalledWithDifferentArgs(invocationAt("at com.FooTest:20"), invocationMatcherAt("at com.Foo:100"));
+        listener.foundStubCalledWithDifferentArgs(invocationAt("at com.FooTest:21"), invocationMatcherAt("at com.Foo:121"));
+
+        //then
+        assertEquals(
+            "[Mockito] Additional stubbing information (see javadoc for StubbingInfo class):\n" +
+            "[Mockito]\n" +
+            "[Mockito] Argument mismatch between stubbing and actual invocation (is stubbing correct in the test?):\n" +
+            "[Mockito]\n" +
+            "[Mockito] 1. Stubbed at com.FooTest:20\n" +
+            "[Mockito]    Invoked at com.Foo:100\n" +
+            "[Mockito] 2. Stubbed at com.FooTest:21\n" +
+            "[Mockito]    Invoked at com.Foo:121", listener.getStubbingInfo());
+    }
+
+    @Test
+    public void informs_about_various_kinds_of_stubs() {
+        //given
+        LoggingListener listener = new LoggingListener(true);
+
+        //when
+        listener.foundUnusedStub(invocationAt("at com.FooTest:30"));
+        listener.foundStubCalledWithDifferentArgs(invocationAt("at com.FooTest:20"), invocationMatcherAt("at com.Foo:100"));
+        listener.foundUnstubbed(invocationMatcherAt("at com.Foo:96"));
+
+        //then
+        assertEquals(
+            "[Mockito] Additional stubbing information (see javadoc for StubbingInfo class):\n" +
+            "[Mockito]\n" +
+            "[Mockito] Argument mismatch between stubbing and actual invocation (is stubbing correct in the test?):\n" +
+            "[Mockito]\n" +
+            "[Mockito] 1. Stubbed at com.FooTest:20\n" +
+            "[Mockito]    Invoked at com.Foo:100\n" +
+            "[Mockito]\n" +
+            "[Mockito] Unused stubbing (perhaps can be removed from the test?):\n" +
+            "[Mockito]\n" +
+            "[Mockito] 1. at com.FooTest:30\n" +
+            "[Mockito]\n" +
+            "[Mockito] Unstubbed method invocations (perhaps missing stubbing in the test?):\n" +
+            "[Mockito]\n" +
+            "[Mockito] 1. at com.Foo:96", listener.getStubbingInfo());
+    }
+
+    @Test
+    public void hides_unstubbed() {
+        //given
+        LoggingListener listener = new LoggingListener(false);
+
+        //when
+        listener.foundUnstubbed(new InvocationBuilder().toInvocationMatcher());
+
+        //then
+        assertEquals("", listener.getStubbingInfo());
+    }
+
+    @Test
+    public void informs_about_unstubbed() {
+        //given
+        LoggingListener listener = new LoggingListener(true);
+
+        //when
+        listener.foundUnstubbed(invocationMatcherAt("com.Foo:20"));
+
+        //then
+        assertEquals(
+                "[Mockito] Additional stubbing information (see javadoc for StubbingInfo class):\n" +
+                "[Mockito]\n" +
+                "[Mockito] Unstubbed method invocations (perhaps missing stubbing in the test?):\n" +
+                "[Mockito]\n" +
+                "[Mockito] 1. com.Foo:20", listener.getStubbingInfo());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/debugging/VerboseMockInvocationLoggerTest.java b/src/test/java/org/mockito/internal/debugging/VerboseMockInvocationLoggerTest.java
new file mode 100644
index 0000000..22f5bb2
--- /dev/null
+++ b/src/test/java/org/mockito/internal/debugging/VerboseMockInvocationLoggerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.handler.NotifiedMethodInvocationReport;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.StubInfoImpl;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Invocation;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class VerboseMockInvocationLoggerTest {
+
+    private VerboseMockInvocationLogger listener;
+
+    private ByteArrayOutputStream output;
+    private Invocation invocation = new InvocationBuilder().toInvocation();
+    private DescribedInvocation stubbedInvocation = new InvocationBuilder().toInvocation();
+
+    @Before
+    public void init_Listener() throws Exception {
+        output = new ByteArrayOutputStream();
+        listener = new VerboseMockInvocationLogger(new PrintStream(output));
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        System.out.println(output);
+    }
+
+    @Test
+    public void should_print_to_system_out() {
+        assertThat(new VerboseMockInvocationLogger().printStream).isSameAs(System.out);
+    }
+
+    @Test
+    public void should_print_invocation_with_return_value() {
+        // when
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, "return value"));
+
+        // then
+        assertThat(printed())
+                .contains(invocation.toString())
+                .contains(invocation.getLocation().toString())
+                .contains("return value");
+    }
+
+    @Test
+    public void should_print_invocation_with_exception() {
+        // when
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, new ThirdPartyException()));
+
+        // then
+        assertThat(printed())
+                .contains(invocation.toString())
+                .contains(invocation.getLocation().toString())
+                .contains(ThirdPartyException.class.getName());
+    }
+
+    @Test
+    public void should_print_if_method_has_not_been_stubbed() throws Exception {
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, "whatever"));
+
+        assertThat(printed()).doesNotContain("stubbed");
+    }
+
+    @Test
+    public void should_print_stubbed_info_if_availbable() throws Exception {
+        invocation.markStubbed(new StubInfoImpl(stubbedInvocation));
+
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, "whatever"));
+
+        assertThat(printed())
+                .contains("stubbed")
+                .contains(stubbedInvocation.getLocation().toString());
+    }
+
+    @Test
+    public void should_log_count_of_interactions() {
+        // when & then
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, new ThirdPartyException()));
+        assertThat(printed()).contains("#1");
+
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, new ThirdPartyException()));
+        assertThat(printed()).contains("#2");
+
+        listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, new ThirdPartyException()));
+        assertThat(printed()).contains("#3");
+    }
+
+    private String printed() {
+        return output.toString();
+    }
+
+    private static class ThirdPartyException extends Exception {
+        private static final long serialVersionUID = 3022739107688491354L;
+    }
+}
diff --git a/src/test/java/org/mockito/internal/debugging/WarningsFinderTest.java b/src/test/java/org/mockito/internal/debugging/WarningsFinderTest.java
new file mode 100644
index 0000000..e0a6352
--- /dev/null
+++ b/src/test/java/org/mockito/internal/debugging/WarningsFinderTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+
+import static java.util.Arrays.asList;
+import static org.mockito.Mockito.only;
+import static org.mockito.Mockito.verify;
+
+public class WarningsFinderTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private FindingsListener listener;
+
+    @Test
+    public void shouldPrintUnusedStub() {
+        // given
+        Invocation unusedStub = new InvocationBuilder().simpleMethod().toInvocation();
+
+        // when
+        WarningsFinder finder = new WarningsFinder(asList(unusedStub), Arrays.<InvocationMatcher>asList());
+        finder.find(listener);
+
+        // then
+        verify(listener, only()).foundUnusedStub(unusedStub);
+    }
+
+    @Test
+    public void shouldPrintUnstubbedInvocation() {
+        // given
+        InvocationMatcher unstubbedInvocation = new InvocationBuilder().differentMethod().toInvocationMatcher();
+
+        // when
+        WarningsFinder finder = new WarningsFinder(Arrays.<Invocation>asList(), Arrays.<InvocationMatcher>asList(unstubbedInvocation));
+        finder.find(listener);
+
+        // then
+        verify(listener, only()).foundUnstubbed(unstubbedInvocation);
+    }
+
+    @Test
+    public void shouldPrintStubWasUsedWithDifferentArgs() {
+        // given
+        Invocation stub = new InvocationBuilder().arg("foo").mock(mock).toInvocation();
+        InvocationMatcher wrongArg = new InvocationBuilder().arg("bar").mock(mock).toInvocationMatcher();
+
+        // when
+        WarningsFinder finder = new WarningsFinder(Arrays.<Invocation> asList(stub), Arrays.<InvocationMatcher> asList(wrongArg));
+        finder.find(listener);
+
+        // then
+        verify(listener, only()).foundStubCalledWithDifferentArgs(stub, wrongArg);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/exceptions/ReporterTest.java b/src/test/java/org/mockito/internal/exceptions/ReporterTest.java
new file mode 100644
index 0000000..6dffddb
--- /dev/null
+++ b/src/test/java/org/mockito/internal/exceptions/ReporterTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.exceptions;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+
+import static org.mockito.Mockito.mock;
+
+public class ReporterTest extends TestBase {
+
+    @Test(expected = TooLittleActualInvocations.class)
+    public void should_let_passing_null_last_actual_stack_trace() throws Exception {
+        throw Reporter.tooLittleActualInvocations(new org.mockito.internal.reporting.Discrepancy(1, 2), new InvocationBuilder().toInvocation(), null);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_throw_correct_exception_for_null_invocation_listener() throws Exception {
+        throw Reporter.invocationListenerDoesNotAcceptNullParameters();
+    }
+
+    @Test(expected = NoInteractionsWanted.class)
+    public void can_use_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_no_more_interaction_wanted() throws Exception {
+        Invocation invocation_with_bogus_default_answer = new InvocationBuilder().mock(mock(IMethods.class, new Returns(false))).toInvocation();
+        throw Reporter.noMoreInteractionsWanted(invocation_with_bogus_default_answer, Collections.<VerificationAwareInvocation>emptyList());
+    }
+
+    @Test(expected = VerificationInOrderFailure.class)
+    public void can_use_print_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_no_more_interaction_wanted_in_order() throws Exception {
+        Invocation invocation_with_bogus_default_answer = new InvocationBuilder().mock(mock(IMethods.class, new Returns(false))).toInvocation();
+        throw Reporter.noMoreInteractionsWantedInOrder(invocation_with_bogus_default_answer);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void can_use_print_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_invalid_argument_position() throws Exception {
+        Invocation invocation_with_bogus_default_answer = new InvocationBuilder().mock(mock(IMethods.class, new Returns(false))).toInvocation();
+        throw Reporter.invalidArgumentPositionRangeAtInvocationTime(invocation_with_bogus_default_answer, true, 0);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void can_use_print_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_wrong_argument_to_return() throws Exception {
+        Invocation invocation_with_bogus_default_answer = new InvocationBuilder().mock(mock(IMethods.class, new Returns(false))).toInvocation();
+        throw Reporter.wrongTypeOfArgumentToReturn(invocation_with_bogus_default_answer, "", String.class, 0);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void can_use_print_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_delegate_method_dont_exists() throws Exception {
+        Invocation dumb_invocation = new InvocationBuilder().toInvocation();
+        IMethods mock_with_bogus_default_answer = mock(IMethods.class, new Returns(false));
+        throw Reporter.delegatedMethodDoesNotExistOnDelegate(dumb_invocation.getMethod(), mock_with_bogus_default_answer, String.class);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void can_use_print_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_delegate_method_has_wrong_return_type() throws Exception {
+        Invocation dumb_invocation = new InvocationBuilder().toInvocation();
+        IMethods mock_with_bogus_default_answer = mock(IMethods.class, new Returns(false));
+        throw Reporter.delegatedMethodHasWrongReturnType(dumb_invocation.getMethod(), dumb_invocation.getMethod(), mock_with_bogus_default_answer, String.class);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void can_use_print_mock_name_even_when_mock_bogus_default_answer_and_when_reporting_injection_failure() throws Exception {
+        IMethods mock_with_bogus_default_answer = mock(IMethods.class, new Returns(false));
+        throw Reporter.cannotInjectDependency(someField(), mock_with_bogus_default_answer, new Exception());
+    }
+
+    private Field someField() {
+        return Mockito.class.getDeclaredFields()[0];
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilterTest.java b/src/test/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilterTest.java
new file mode 100644
index 0000000..a92bf1f
--- /dev/null
+++ b/src/test/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilterTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.exceptions.stacktrace;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.TraceBuilder;
+import org.mockito.internal.configuration.ConfigurationAccess;
+import org.mockitoutil.TestBase;
+
+import static org.mockitoutil.Conditions.onlyThoseClassesInStackTrace;
+
+public class ConditionalStackTraceFilterTest extends TestBase {
+
+    private ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+
+    @Test
+    public void shouldNotFilterWhenConfigurationSaysNo() {
+        ConfigurationAccess.getConfig().overrideCleansStackTrace(false);
+
+        Throwable t = new TraceBuilder().classes(
+                "org.test.MockitoSampleTest",
+                "org.mockito.Mockito"
+        ).toThrowable();
+
+        filter.filter(t);
+
+        Assertions.assertThat(t).has(onlyThoseClassesInStackTrace("org.mockito.Mockito", "org.test.MockitoSampleTest"));
+    }
+
+    @Test
+    public void shouldFilterWhenConfigurationSaysYes() {
+        ConfigurationAccess.getConfig().overrideCleansStackTrace(true);
+
+        Throwable t = new TraceBuilder().classes(
+                "org.test.MockitoSampleTest",
+                "org.mockito.Mockito"
+        ).toThrowable();
+
+        filter.filter(t);
+
+        Assertions.assertThat(t).has(onlyThoseClassesInStackTrace("org.test.MockitoSampleTest"));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilterTest.java b/src/test/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilterTest.java
new file mode 100644
index 0000000..5c77fd2
--- /dev/null
+++ b/src/test/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilterTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.exceptions.stacktrace;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.TraceBuilder;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockitoutil.Conditions.onlyThoseClasses;
+
+public class StackTraceFilterTest extends TestBase {
+
+    private final StackTraceFilter filter = new StackTraceFilter();
+
+    @Test
+    public void shouldFilterOutCglibGarbage() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+            "MockitoExampleTest",
+            "List$$EnhancerByMockitoWithCGLIB$$2c406024"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("MockitoExampleTest"));
+    }
+
+    @Test
+    public void shouldFilterOutByteBuddyGarbage() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "MockitoExampleTest",
+                "org.testcase.MockedClass$MockitoMock$1882975947.doSomething(Unknown Source)"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("MockitoExampleTest"));
+    }
+
+
+    @Test
+    public void shouldFilterOutMockitoPackage() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+            "org.test.MockitoSampleTest",
+            "org.mockito.Mockito"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("org.test.MockitoSampleTest"));
+    }
+
+    @Test
+    public void shouldNotFilterOutTracesMiddleGoodTraces() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "org.test.MockitoSampleTest",
+                "org.test.TestSupport",
+                "org.mockito.Mockito",
+                "org.test.TestSupport",
+                "org.mockito.Mockito"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("org.test.TestSupport", "org.test.TestSupport", "org.test.MockitoSampleTest"));
+    }
+
+    @Test
+    public void shouldKeepRunners() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "org.mockito.runners.Runner",
+                "junit.stuff",
+                "org.test.MockitoSampleTest",
+                "org.mockito.Mockito"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("org.test.MockitoSampleTest", "junit.stuff", "org.mockito.runners.Runner"));
+    }
+
+    @Test
+    public void shouldNotFilterElementsAboveMockitoJUnitRule() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:16)",
+                "org.mockito.runners.Runner",
+                "junit.stuff",
+                "org.test.MockitoSampleTest",
+                "org.mockito.internal.MockitoCore.verifyNoMoreInteractions",
+                "org.mockito.internal.debugging.LocationImpl"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("org.test.MockitoSampleTest", "junit.stuff", "org.mockito.runners.Runner","org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:16)"));
+    }
+
+    @Test
+    public void shouldKeepInternalRunners() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "org.mockito.internal.runners.Runner",
+                "org.test.MockitoSampleTest"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, false);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses("org.test.MockitoSampleTest", "org.mockito.internal.runners.Runner"));
+    }
+
+    @Test
+    public void shouldStartFilteringAndKeepTop() {
+        //given
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "org.test.Good",
+                "org.mockito.internal.Bad",
+                "org.test.MockitoSampleTest"
+        ).toTraceArray();
+
+        //when
+        StackTraceElement[] filtered = filter.filter(t, true);
+
+        //then
+        Assertions.assertThat(filtered).has(onlyThoseClasses("org.test.MockitoSampleTest", "org.test.Good"));
+    }
+
+    @Test
+    public void shouldKeepGoodTraceFromTheTopBecauseRealImplementationsOfSpiesSometimesThrowExceptions() {
+        StackTraceElement[] t = new TraceBuilder().classes(
+                "org.good.Trace",
+                "org.yet.another.good.Trace",
+                "org.mockito.internal.to.be.Filtered",
+                "org.test.MockitoSampleTest"
+        ).toTraceArray();
+
+        StackTraceElement[] filtered = filter.filter(t, true);
+
+        Assertions.assertThat(filtered).has(onlyThoseClasses(
+                "org.test.MockitoSampleTest",
+                "org.yet.another.good.Trace",
+                "org.good.Trace"
+                ));
+    }
+
+    @Test
+    public void shouldReturnEmptyArrayWhenInputIsEmpty() throws Exception {
+        //when
+        StackTraceElement[] filtered = filter.filter(new StackTraceElement[0], false);
+        //then
+        assertEquals(0, filtered.length);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/exceptions/util/ScenarioPrinterTest.java b/src/test/java/org/mockito/internal/exceptions/util/ScenarioPrinterTest.java
new file mode 100644
index 0000000..f0e22d4
--- /dev/null
+++ b/src/test/java/org/mockito/internal/exceptions/util/ScenarioPrinterTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.exceptions.util;
+
+import org.junit.Test;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SuppressWarnings("unchecked")
+public class ScenarioPrinterTest extends TestBase {
+
+    ScenarioPrinter sp = new ScenarioPrinter();
+
+    @Test
+    public void shouldPrintInvocations() {
+        //given
+        Invocation verified = new InvocationBuilder().simpleMethod().verified().toInvocation();
+        Invocation unverified = new InvocationBuilder().differentMethod().toInvocation();
+
+        //when
+        String out = sp.print((List) asList(verified, unverified));
+
+        //then
+        assertThat(out)
+            .contains("1. -> at")
+            .contains("2. [?]-> at");
+    }
+
+    @Test
+    public void shouldNotPrintInvocationsWhenSingleUnwanted() {
+        //given
+        Invocation unverified = new InvocationBuilder().differentMethod().toInvocation();
+
+        //when
+        String out = sp.print((List) asList(unverified));
+
+        //then
+        assertThat(out).contains("Actually, above is the only interaction with this mock.");
+    }
+}
diff --git a/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java b/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java
new file mode 100644
index 0000000..2f250b2
--- /dev/null
+++ b/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java
@@ -0,0 +1,112 @@
+package org.mockito.internal.framework;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.MockSettings;
+import org.mockito.StateMaster;
+import org.mockito.exceptions.misusing.RedundantListenerException;
+import org.mockito.listeners.MockCreationListener;
+import org.mockito.listeners.MockitoListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+import static org.mockitoutil.ThrowableAssert.assertThat;
+
+public class DefaultMockitoFrameworkTest extends TestBase {
+
+    private DefaultMockitoFramework framework = new DefaultMockitoFramework();
+
+    @After public void clearListeners() {
+        new StateMaster().clearMockitoListeners();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void prevents_adding_null_listener() {
+        framework.addListener(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void prevents_removing_null_listener() {
+        framework.removeListener(null);
+    }
+
+    @Test
+    public void ok_to_remove_unknown_listener() {
+        //it is safe to remove listener that was not added before
+        framework.removeListener(new MockitoListener() {});
+    }
+
+    @Test
+    public void ok_to_remove_listener_multiple_times() {
+        MockitoListener listener = new MockitoListener() {};
+
+        //when
+        framework.addListener(listener);
+
+        //then it is ok to:
+        framework.removeListener(listener);
+        framework.removeListener(listener);
+    }
+
+    @Test
+    public void adds_creation_listener() {
+        //given creation listener is added
+        MockCreationListener listener = mock(MockCreationListener.class);
+        framework.addListener(listener);
+
+        //when
+        MockSettings settings = withSettings().name("my list");
+        List mock = mock(List.class, settings);
+        Set mock2 = mock(Set.class);
+
+        //then
+        verify(listener).onMockCreated(eq(mock), any(MockCreationSettings.class));
+        verify(listener).onMockCreated(eq(mock2), any(MockCreationSettings.class));
+        verifyNoMoreInteractions(listener);
+    }
+
+    @Test
+    public void removes_creation_listener() {
+        //given creation listener is added
+        MockCreationListener listener = mock(MockCreationListener.class);
+        framework.addListener(listener);
+
+        //and hooked up correctly
+        mock(List.class);
+        verify(listener).onMockCreated(ArgumentMatchers.any(), any(MockCreationSettings.class));
+
+        //when
+        framework.removeListener(listener);
+        mock(Set.class);
+
+        //then
+        verifyNoMoreInteractions(listener);
+    }
+
+    @Test public void prevents_duplicate_listeners_of_the_same_type() {
+        //given creation listener is added
+        framework.addListener(new MyListener());
+
+        assertThat(new Runnable() {
+            @Override
+            public void run() {
+                framework.addListener(new MyListener());
+            }
+        })  .throwsException(RedundantListenerException.class)
+            .throwsMessage("\n" +
+                    "Problems adding Mockito listener.\n" +
+                    "Listener of type 'MyListener' has already been added and not removed.\n" +
+                    "It indicates that previous listener was not removed according to the API.\n" +
+                    "When you add a listener, don't forget to remove the listener afterwards:\n" +
+                    "  Mockito.framework().removeListener(myListener);\n" +
+                    "For more information, see the javadoc for RedundantListenerException class.");
+    }
+
+    private static class MyListener implements MockitoListener {}
+}
diff --git a/src/test/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractorTest.java b/src/test/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractorTest.java
new file mode 100644
index 0000000..0e48717
--- /dev/null
+++ b/src/test/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractorTest.java
@@ -0,0 +1,131 @@
+package org.mockito.internal.hamcrest;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.internal.hamcrest.MatcherGenericTypeExtractor.genericTypeOfMatcher;
+
+public class MatcherGenericTypeExtractorTest extends TestBase {
+
+    //traditional inner class for matcher
+    private class IntMatcher extends BaseMatcher<Integer> {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
+    //static class with matcher
+    private static class StaticIntMatcher extends BaseMatcher<Integer> {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
+    //static subclass
+    private static class StaticIntMatcherSubclass extends StaticIntMatcher {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
+    //non-generic
+    @SuppressWarnings("rawtypes")
+    private static class NonGenericMatcher extends BaseMatcher {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
+    //Matcher interface implementation (instead of the BaseMatcher)
+    private class IntMatcherFromInterface extends BaseMatcher<Integer> {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeMismatch(Object item, Description mismatchDescription) {}
+        public void describeTo(Description description) {}
+    }
+
+    //Static Matcher interface implementation (instead of the BaseMatcher)
+    private static class StaticIntMatcherFromInterface extends BaseMatcher<Integer> {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeMismatch(Object item, Description mismatchDescription) {}
+        public void describeTo(Description description) {}
+    }
+
+    //non-generic matcher implementing the interface
+    @SuppressWarnings("rawtypes")
+    private static class NonGenericMatcherFromInterface extends BaseMatcher {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeMismatch(Object item, Description mismatchDescription) {}
+        public void describeTo(Description description) {}
+    }
+
+    private interface IMatcher extends Matcher<Integer> {}
+
+    //non-generic matcher implementing the interface
+    private static class SubclassGenericMatcherFromInterface extends BaseMatcher<Integer> implements Serializable, Cloneable, IMatcher {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeMismatch(Object item, Description mismatchDescription) {}
+        public void describeTo(Description description) {}
+    }
+
+    //I refuse to comment on the sanity of this case
+    private static class InsaneEdgeCase extends SubclassGenericMatcherFromInterface {}
+
+    @Test
+    public void findsGenericType() {
+        assertEquals(Integer.class, genericTypeOfMatcher(IntMatcher.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(StaticIntMatcher.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(IntMatcherFromInterface.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(StaticIntMatcherSubclass.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(IntMatcherFromInterface.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(StaticIntMatcherFromInterface.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(SubclassGenericMatcherFromInterface.class));
+        assertEquals(Integer.class, genericTypeOfMatcher(InsaneEdgeCase.class));
+
+        assertEquals(Integer.class, genericTypeOfMatcher(new BaseMatcher<Integer>() {
+            public void describeTo(Description description) {
+            }
+
+            public boolean matches(Object o) {
+                return false;
+            }
+        }.getClass()));
+        assertEquals(Integer.class, genericTypeOfMatcher(new BaseMatcher<Integer>() {
+            public void describeTo(Description description) {
+            }
+
+            public boolean matches(Object o) {
+                return false;
+            }
+
+            public void describeMismatch(Object item, Description mismatchDescription) {
+            }
+        }.getClass()));
+
+        assertEquals(Object.class, genericTypeOfMatcher(Object.class));
+        assertEquals(Object.class, genericTypeOfMatcher(String.class));
+        assertEquals(Object.class, genericTypeOfMatcher(HashMap.class));
+        assertEquals(Object.class, genericTypeOfMatcher(new HashMap<String, String>() {
+        }.getClass()));
+        assertEquals(Object.class, genericTypeOfMatcher(NonGenericMatcher.class));
+        assertEquals(Object.class, genericTypeOfMatcher(NonGenericMatcherFromInterface.class));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/handler/InvocationNotifierHandlerTest.java b/src/test/java/org/mockito/internal/handler/InvocationNotifierHandlerTest.java
new file mode 100644
index 0000000..6022625
--- /dev/null
+++ b/src/test/java/org/mockito/internal/handler/InvocationNotifierHandlerTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.listeners.MethodInvocationReport;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.willThrow;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+
+@RunWith(MockitoJUnitRunner.class)
+@SuppressWarnings("unchecked")
+public class InvocationNotifierHandlerTest {
+    private static final String SOME_LOCATION = "some location";
+    private static final RuntimeException SOME_EXCEPTION = new RuntimeException();
+    private static final OutOfMemoryError SOME_ERROR = new OutOfMemoryError();
+    private static final Answer<?> SOME_ANSWER = mock(Answer.class);
+
+
+    @Mock private InvocationListener listener1;
+    @Mock private InvocationListener listener2;
+    @Spy private CustomListener customListener;
+
+    @Mock private Invocation invocation;
+    @Mock private MockHandlerImpl<ArrayList<Answer<?>>> mockHandler;
+
+    private InvocationNotifierHandler<ArrayList<Answer<?>>> notifier;
+
+    @Before
+    public void setUp() throws Exception {
+        notifier = new InvocationNotifierHandler<ArrayList<Answer<?>>>(
+                mockHandler,
+                (MockCreationSettings<ArrayList<Answer<?>>>) new MockSettingsImpl<ArrayList<Answer<?>>>().invocationListeners(customListener, listener1, listener2)
+        );
+    }
+
+    @Test
+    public void should_notify_all_listeners_when_calling_delegate_handler() throws Throwable {
+        // given
+        given(mockHandler.handle(invocation)).willReturn("returned value");
+
+        // when
+        notifier.handle(invocation);
+
+        // then
+        verify(listener1).reportInvocation(new NotifiedMethodInvocationReport(invocation, "returned value"));
+        verify(listener2).reportInvocation(new NotifiedMethodInvocationReport(invocation, "returned value"));
+    }
+
+    @Test
+    public void should_notify_all_listeners_when_called_delegate_handler_returns_ex() throws Throwable {
+        // given
+        Exception computedException = new Exception("computed");
+        given(mockHandler.handle(invocation)).willReturn(computedException);
+
+        // when
+        notifier.handle(invocation);
+
+        // then
+        verify(listener1).reportInvocation(new NotifiedMethodInvocationReport(invocation, (Object) computedException));
+        verify(listener2).reportInvocation(new NotifiedMethodInvocationReport(invocation, (Object) computedException));
+    }
+
+    @Test(expected = ParseException.class)
+    public void should_notify_all_listeners_when_called_delegate_handler_throws_exception_and_rethrow_it() throws Throwable {
+        // given
+        ParseException parseException = new ParseException("", 0);
+        given(mockHandler.handle(invocation)).willThrow(parseException);
+
+        // when
+        try {
+            notifier.handle(invocation);
+            fail();
+        } finally {
+            // then
+            verify(listener1).reportInvocation(new NotifiedMethodInvocationReport(invocation, parseException));
+            verify(listener2).reportInvocation(new NotifiedMethodInvocationReport(invocation, parseException));
+        }
+    }
+
+    @Test
+    public void should_report_listener_exception() throws Throwable {
+        willThrow(new NullPointerException()).given(customListener).reportInvocation(any(MethodInvocationReport.class));
+
+        try {
+            notifier.handle(invocation);
+            fail();
+        } catch (MockitoException me) {
+            assertThat(me.getMessage())
+                    .contains("invocation listener")
+                    .contains("CustomListener")
+                    .contains("threw an exception")
+                    .contains("NullPointerException");
+        }
+    }
+
+    @Test
+    public void should_delegate_all_MockHandlerInterface_to_the_parameterized_MockHandler() throws Exception {
+        notifier.getInvocationContainer();
+        notifier.getMockSettings();
+        notifier.setAnswersForStubbing(new ArrayList<Answer<?>>());
+
+        verify(mockHandler).getInvocationContainer();
+        verify(mockHandler).getMockSettings();
+        verify(mockHandler).setAnswersForStubbing(ArgumentMatchers.<Answer<?>>anyList());
+    }
+
+    private static class CustomListener implements InvocationListener {
+        public void reportInvocation(MethodInvocationReport methodInvocationReport) {
+            // nop
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/handler/MockHandlerFactoryTest.java b/src/test/java/org/mockito/internal/handler/MockHandlerFactoryTest.java
new file mode 100644
index 0000000..b595450
--- /dev/null
+++ b/src/test/java/org/mockito/internal/handler/MockHandlerFactoryTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static org.mockito.internal.handler.MockHandlerFactory.createMockHandler;
+
+/**
+ * by Szczepan Faber, created at: 5/22/12
+ */
+public class MockHandlerFactoryTest extends TestBase {
+
+    private final IMethods mock = Mockito.mock(IMethods.class);
+
+    @Test
+    //see issue 331
+    public void handle_result_must_not_be_null_for_primitives() throws Throwable {
+        //given:
+        MockCreationSettings<?> settings = (MockCreationSettings<?>) new MockSettingsImpl().defaultAnswer(new Returns(null));
+		InternalMockHandler<?> handler = createMockHandler(settings);
+
+        mock.intReturningMethod();
+        Invocation invocation = super.getLastInvocation();
+
+        //when:
+        Object result = handler.handle(invocation);
+
+        //then null value is not a valid result for a primitive
+        assertNotNull(result);
+        assertEquals(0, result);
+    }
+
+    @Test
+    //see issue 331
+    public void valid_handle_result_is_permitted() throws Throwable {
+        //given:
+        MockCreationSettings<?> settings = (MockCreationSettings<?>) new MockSettingsImpl().defaultAnswer(new Returns(123));
+        InternalMockHandler<?> handler =  createMockHandler(settings);
+
+        mock.intReturningMethod();
+        Invocation invocation = super.getLastInvocation();
+
+        //when:
+        Object result = handler.handle(invocation);
+
+        //then
+        assertEquals(123, result);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/handler/MockHandlerImplTest.java b/src/test/java/org/mockito/internal/handler/MockHandlerImplTest.java
new file mode 100644
index 0000000..1528b36
--- /dev/null
+++ b/src/test/java/org/mockito/internal/handler/MockHandlerImplTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.handler;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+import org.mockito.exceptions.misusing.WrongTypeOfReturnValue;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationImpl;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.MatchersBinder;
+import org.mockito.internal.progress.ArgumentMatcherStorage;
+import org.mockito.internal.stubbing.InvocationContainerImpl;
+import org.mockito.internal.stubbing.StubbedInvocationMatcher;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.invocation.Invocation;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.listeners.MethodInvocationReport;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+
+@SuppressWarnings({"unchecked", "serial"})
+public class MockHandlerImplTest extends TestBase {
+
+    private StubbedInvocationMatcher stubbedInvocationMatcher = mock(StubbedInvocationMatcher.class);
+    private Invocation invocation = mock(InvocationImpl.class);
+
+
+    @Test
+    public void should_remove_verification_mode_even_when_invalid_matchers() throws Throwable {
+        // given
+        Invocation invocation = new InvocationBuilder().toInvocation();
+        @SuppressWarnings("rawtypes")
+        MockHandlerImpl<?> handler = new MockHandlerImpl(new MockSettingsImpl());
+        mockingProgress().verificationStarted(VerificationModeFactory.atLeastOnce());
+        handler.matchersBinder = new MatchersBinder() {
+            public InvocationMatcher bindMatchers(ArgumentMatcherStorage argumentMatcherStorage, Invocation invocation) {
+                throw new InvalidUseOfMatchersException();
+            }
+        };
+
+        try {
+            // when
+            handler.handle(invocation);
+
+            // then
+            fail();
+        } catch (InvalidUseOfMatchersException ignored) {
+        }
+
+        assertNull(mockingProgress().pullVerificationMode());
+    }
+
+
+    @Test(expected = MockitoException.class)
+    public void should_throw_mockito_exception_when_invocation_handler_throws_anything() throws Throwable {
+        // given
+        InvocationListener throwingListener = mock(InvocationListener.class);
+        doThrow(new Throwable()).when(throwingListener).reportInvocation(any(MethodInvocationReport.class));
+        MockHandlerImpl<?> handler = create_correctly_stubbed_handler(throwingListener);
+
+        // when
+        handler.handle(invocation);
+    }
+
+    @Test(expected = WrongTypeOfReturnValue.class)
+    public void should_report_bogus_default_answer() throws Throwable {
+        MockSettingsImpl mockSettings = mock(MockSettingsImpl.class);
+        MockHandlerImpl<?> handler = new MockHandlerImpl(mockSettings);
+        given(mockSettings.getDefaultAnswer()).willReturn(new Returns(AWrongType.WRONG_TYPE));
+
+        @SuppressWarnings("unused") // otherwise cast is not done
+        String there_should_not_be_a_CCE_here = (String) handler.handle(
+                new InvocationBuilder().method(Object.class.getDeclaredMethod("toString")).toInvocation()
+        );
+    }
+
+    private MockHandlerImpl<?> create_correctly_stubbed_handler(InvocationListener throwingListener) {
+        MockHandlerImpl<?> handler = create_handler_with_listeners(throwingListener);
+        stub_ordinary_invocation_with_given_return_value(handler);
+        return handler;
+    }
+
+    private void stub_ordinary_invocation_with_given_return_value(MockHandlerImpl<?> handler) {
+        stub_ordinary_invocation_with_invocation_matcher(handler, stubbedInvocationMatcher);
+    }
+
+
+    private void stub_ordinary_invocation_with_invocation_matcher(MockHandlerImpl<?> handler, StubbedInvocationMatcher value) {
+        handler.invocationContainerImpl = mock(InvocationContainerImpl.class);
+        given(handler.invocationContainerImpl.findAnswerFor(any(InvocationImpl.class))).willReturn(value);
+    }
+
+
+    private MockHandlerImpl<?> create_handler_with_listeners(InvocationListener... listener) {
+        @SuppressWarnings("rawtypes")
+        MockHandlerImpl<?> handler = new MockHandlerImpl(mock(MockSettingsImpl.class));
+        handler.matchersBinder = mock(MatchersBinder.class);
+        given(handler.getMockSettings().getInvocationListeners()).willReturn(Arrays.asList(listener));
+        return handler;
+    }
+
+    private static class AWrongType {
+        public static final AWrongType WRONG_TYPE = new AWrongType();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/invocation/InvocationBuilder.java b/src/test/java/org/mockito/internal/invocation/InvocationBuilder.java
new file mode 100644
index 0000000..e08b221
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/InvocationBuilder.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import org.mockito.Mockito;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockito.internal.util.reflection.AccessibilityChanger;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+import org.mockitousage.IMethods;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Build an invocation.
+ */
+@SuppressWarnings("unchecked")
+public class InvocationBuilder {
+
+    private String methodName = "simpleMethod";
+    private int sequenceNumber = 0;
+    private Object[] args = new Object[]{};
+    private Object mock = Mockito.mock(IMethods.class);
+    private Method method;
+    private boolean verified;
+    private List<Class<?>> argTypes;
+    private Location location;
+
+    /**
+     * Build the invocation
+     * <p>
+     * If the method was not specified, use IMethods methods.
+     *
+     * @return invocation
+     */
+    public Invocation toInvocation() {
+        if (method == null) {
+            if (argTypes == null) {
+                argTypes = new LinkedList<Class<?>>();
+                for (Object arg : args) {
+                    if (arg == null) {
+                        argTypes.add(Object.class);
+                    } else {
+                        argTypes.add(arg.getClass());
+                    }
+                }
+            }
+
+            try {
+                method = IMethods.class.getMethod(methodName, argTypes.toArray(new Class[argTypes.size()]));
+            } catch (Exception e) {
+                throw new RuntimeException("builder only creates invocations of IMethods interface", e);
+            }
+        }
+
+        Invocation i = new InvocationImpl(mock,
+                                          new SerializableMethod(method),
+                                          args,
+                                          sequenceNumber,
+                                          toDumbRealMethod(),
+                                          location == null ? new LocationImpl() : location);
+        if (verified) {
+            i.markVerified();
+        }
+        return i;
+    }
+
+    private RealMethod toDumbRealMethod() {
+        return new RealMethod() {
+            @Override
+            public Object invoke(Object target, Object[] arguments) throws Throwable {
+                AccessibilityChanger accessibilityChanger = new AccessibilityChanger();
+                try {
+                    accessibilityChanger.enableAccess(method);
+                    return method.invoke(target, arguments);
+                } finally {
+                    accessibilityChanger.safelyDisableAccess(method);
+                }
+
+            }
+        };
+    }
+
+    public InvocationBuilder method(String methodName) {
+        this.methodName = methodName;
+        return this;
+    }
+
+    public InvocationBuilder seq(int sequenceNumber) {
+        this.sequenceNumber = sequenceNumber;
+        return this;
+    }
+
+    public InvocationBuilder args(Object... args) {
+        this.args = args;
+        return this;
+    }
+
+    public InvocationBuilder arg(Object o) {
+        this.args = new Object[]{o};
+        return this;
+    }
+
+    public InvocationBuilder mock(Object mock) {
+        this.mock = mock;
+        return this;
+    }
+
+    public InvocationBuilder method(Method method) {
+        this.method = method;
+        return this;
+    }
+
+    public InvocationBuilder verified() {
+        this.verified = true;
+        return this;
+    }
+
+    public InvocationMatcher toInvocationMatcher() {
+        return new InvocationMatcher(toInvocation());
+    }
+
+    public InvocationBuilder simpleMethod() {
+        return this.method("simpleMethod");
+    }
+
+    public InvocationBuilder differentMethod() {
+        return this.method("differentMethod");
+    }
+
+    public InvocationBuilder argTypes(Class<?>... argTypes) {
+        this.argTypes = asList(argTypes);
+        return this;
+    }
+
+    public InvocationBuilder location(final String location) {
+        this.location = new Location() {
+            public String toString() {
+                return location;
+            }
+        };
+        return this;
+    }
+}
diff --git a/src/test/java/org/mockito/internal/invocation/InvocationImplTest.java b/src/test/java/org/mockito/internal/invocation/InvocationImplTest.java
new file mode 100644
index 0000000..5e7e48e
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/InvocationImplTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockito.internal.matchers.ArrayEquals;
+import org.mockito.internal.matchers.Equals;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static junit.framework.TestCase.*;
+
+@SuppressWarnings({"unchecked"})
+public class InvocationImplTest extends TestBase {
+
+    private Invocation invocation;
+
+    @Before
+    public void setup() throws Exception {
+        invocation = new InvocationBuilder().args(" ").mock("mock").toInvocation();
+    }
+
+    @Test
+    public void shouldKnowIfIsEqualTo() {
+        Invocation equal =                  new InvocationBuilder().args(" ").mock("mock").toInvocation();
+        Invocation nonEqual =               new InvocationBuilder().args("X").mock("mock").toInvocation();
+        Invocation withNewStringInstance =  new InvocationBuilder().args(new String(" ")).mock("mock").toInvocation();
+
+        assertFalse(invocation.equals(null));
+        assertFalse(invocation.equals(""));
+        assertTrue(invocation.equals(equal));
+        assertFalse(invocation.equals(nonEqual));
+        assertTrue(invocation.equals(withNewStringInstance));
+    }
+
+    @Test
+    public void shouldEqualToNotConsiderSequenceNumber() {
+        Invocation equal = new InvocationBuilder().args(" ").mock("mock").seq(2).toInvocation();
+
+        assertTrue(invocation.equals(equal));
+        assertTrue(invocation.getSequenceNumber() != equal.getSequenceNumber());
+    }
+
+    @Test
+    public void shouldBeACitizenOfHashes() {
+        Map<Invocation, String> map = new HashMap<Invocation, String>();
+        map.put(invocation, "one");
+        assertEquals("one", map.get(invocation));
+    }
+
+    @Test
+    public void shouldPrintMethodName() {
+        invocation = new InvocationBuilder().toInvocation();
+        assertEquals("iMethods.simpleMethod();", invocation.toString());
+    }
+
+    @Test
+    public void shouldPrintMethodArgs() {
+        invocation = new InvocationBuilder().args("foo").toInvocation();
+        Assertions.assertThat(invocation.toString()).endsWith("simpleMethod(\"foo\");");
+    }
+
+    @Test
+    public void shouldPrintMethodIntegerArgAndString() {
+        invocation = new InvocationBuilder().args("foo", 1).toInvocation();
+        Assertions.assertThat(invocation.toString()).endsWith("simpleMethod(\"foo\", 1);");
+    }
+
+    @Test
+    public void shouldPrintNull() {
+        invocation = new InvocationBuilder().args((String) null).toInvocation();
+        Assertions.assertThat(invocation.toString()).endsWith("simpleMethod(null);");
+    }
+
+    @Test
+    public void shouldPrintArray() {
+        invocation = new InvocationBuilder().method("oneArray").args(new int[] { 1, 2, 3 }).toInvocation();
+        Assertions.assertThat(invocation.toString()).endsWith("oneArray([1, 2, 3]);");
+    }
+
+    @Test
+    public void shouldPrintNullIfArrayIsNull() throws Exception {
+        Method m = IMethods.class.getMethod("oneArray", Object[].class);
+        invocation = new InvocationBuilder().method(m).args((Object) null).toInvocation();
+        Assertions.assertThat(invocation.toString()).endsWith("oneArray(null);");
+    }
+
+    @Test
+    public void shouldPrintArgumentsInMultilinesWhenGetsTooBig() {
+        invocation = new InvocationBuilder().args("veeeeery long string that makes it ugly in one line", 1).toInvocation();
+        Assertions.assertThat(invocation.toString()).endsWith(
+                "simpleMethod(" +
+                        "\n" +
+                        "    \"veeeeery long string that makes it ugly in one line\"," +
+                        "\n" +
+                        "    1" +
+                        "\n" +
+                        ");");
+    }
+
+    @Test
+    public void shouldTransformArgumentsToMatchers() throws Exception {
+        Invocation i = new InvocationBuilder().args("foo", new String[]{"bar"}).toInvocation();
+        List matchers = ArgumentsProcessor.argumentsToMatchers(i.getArguments());
+
+        assertEquals(2, matchers.size());
+        assertEquals(Equals.class, matchers.get(0).getClass());
+        assertEquals(ArrayEquals.class, matchers.get(1).getClass());
+    }
+
+    class Foo {
+        public String bark() {
+            return "woof";
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToCallRealMethod() throws Throwable {
+        //when
+        Invocation invocation = invocationOf(Foo.class, "bark", new RealMethod() {
+            public Object invoke(Object target, Object[] arguments) throws Throwable {
+                return new Foo().bark();
+            }});
+        //then
+        assertEquals("woof", invocation.callRealMethod());
+    }
+
+    @Test
+    public void shouldScreamWhenCallingRealMethodOnInterface() throws Throwable {
+        //given
+        Invocation invocationOnInterface = new InvocationBuilder().toInvocation();
+
+        try {
+            //when
+            invocationOnInterface.callRealMethod();
+            //then
+            fail();
+        } catch(MockitoException e) {}
+    }
+
+    @Test
+    public void shouldReturnCastedArgumentAt(){
+        //given
+        int argument = 42;
+        Invocation invocationOnInterface = new InvocationBuilder().method("twoArgumentMethod").
+            argTypes(int.class, int.class).args(1, argument).toInvocation();
+
+        //when
+        int secondArgument = (Integer) invocationOnInterface.getArgument(1);
+
+        //then
+        assertTrue(secondArgument == argument);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/invocation/InvocationMarkerTest.java b/src/test/java/org/mockito/internal/invocation/InvocationMarkerTest.java
new file mode 100644
index 0000000..fd6d638
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/InvocationMarkerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.junit.Test;
+import org.mockito.internal.verification.InOrderContextImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MatchableInvocation;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static junit.framework.TestCase.*;
+
+public class InvocationMarkerTest extends TestBase {
+
+    @Test
+    public void shouldMarkInvocationAsVerified() {
+        //given
+        Invocation i = new InvocationBuilder().toInvocation();
+        InvocationMatcher im = new InvocationBuilder().toInvocationMatcher();
+        assertFalse(i.isVerified());
+
+        //when
+        InvocationMarker.markVerified(Arrays.asList(i), im);
+
+        //then
+        assertTrue(i.isVerified());
+    }
+
+    @Test
+    public void shouldCaptureArguments() {
+        //given
+        Invocation i = new InvocationBuilder().toInvocation();
+        final AtomicReference<Invocation> box = new AtomicReference<Invocation>();
+        MatchableInvocation c = new InvocationMatcher(i) {
+            public void captureArgumentsFrom(Invocation i) {
+                box.set(i);
+            }};
+
+        //when
+        InvocationMarker.markVerified(Arrays.asList(i), c);
+
+        //then
+        assertEquals(i, box.get());
+    }
+
+    @Test
+    public void shouldMarkInvocationsAsVerifiedInOrder() {
+        //given
+        InOrderContextImpl context = new InOrderContextImpl();
+
+        Invocation i = new InvocationBuilder().toInvocation();
+        InvocationMatcher im = new InvocationBuilder().toInvocationMatcher();
+        assertFalse(context.isVerified(i));
+        assertFalse(i.isVerified());
+
+        //when
+        InvocationMarker.markVerifiedInOrder(Arrays.asList(i), im, context);
+
+        //then
+        assertTrue(context.isVerified(i));
+        assertTrue(i.isVerified());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/invocation/InvocationMatcherTest.java b/src/test/java/org/mockito/internal/invocation/InvocationMatcherTest.java
new file mode 100644
index 0000000..25b81f5
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/InvocationMatcherTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.matchers.Any.ANY;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.internal.matchers.CapturingMatcher;
+import org.mockito.internal.matchers.Equals;
+import org.mockito.internal.matchers.NotNull;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+@SuppressWarnings("unchecked")
+public class InvocationMatcherTest extends TestBase {
+
+    private InvocationMatcher simpleMethod;
+    @Mock private IMethods mock;
+
+    @Before
+    public void setup() {
+        simpleMethod = new InvocationBuilder().mock(mock).simpleMethod().toInvocationMatcher();
+    }
+
+    @Test
+    public void should_be_a_citizen_of_hashes() throws Exception {
+        Invocation invocation = new InvocationBuilder().toInvocation();
+        Invocation invocationTwo = new InvocationBuilder().args("blah").toInvocation();
+
+        Map<InvocationMatcher, String> map = new HashMap<InvocationMatcher, String>();
+        map.put(new InvocationMatcher(invocation), "one");
+        map.put(new InvocationMatcher(invocationTwo), "two");
+
+        assertEquals(2, map.size());
+    }
+
+    @Test
+    public void should_not_equal_if_number_of_arguments_differ() throws Exception {
+        InvocationMatcher withOneArg = new InvocationMatcher(new InvocationBuilder().args("test").toInvocation());
+        InvocationMatcher withTwoArgs = new InvocationMatcher(new InvocationBuilder().args("test", 100).toInvocation());
+
+        assertFalse(withOneArg.equals(null));
+        assertFalse(withOneArg.equals(withTwoArgs));
+    }
+
+    @Test
+    public void should_to_string_with_matchers() throws Exception {
+        ArgumentMatcher m = NotNull.NOT_NULL;
+        InvocationMatcher notNull = new InvocationMatcher(new InvocationBuilder().toInvocation(), asList(m));
+        ArgumentMatcher mTwo = new Equals('x');
+        InvocationMatcher equals = new InvocationMatcher(new InvocationBuilder().toInvocation(), asList(mTwo));
+
+        assertThat(notNull.toString()).contains("simpleMethod(notNull())");
+        assertThat(equals.toString()).contains("simpleMethod('x')");
+    }
+
+    @Test
+    public void should_know_if_is_similar_to() throws Exception {
+        Invocation same = new InvocationBuilder().mock(mock).simpleMethod().toInvocation();
+        assertTrue(simpleMethod.hasSimilarMethod(same));
+
+        Invocation different = new InvocationBuilder().mock(mock).differentMethod().toInvocation();
+        assertFalse(simpleMethod.hasSimilarMethod(different));
+    }
+
+    @Test
+    public void should_not_be_similar_to_verified_invocation() throws Exception {
+        Invocation verified = new InvocationBuilder().simpleMethod().verified().toInvocation();
+        assertFalse(simpleMethod.hasSimilarMethod(verified));
+    }
+
+    @Test
+    public void should_not_be_similar_if_mocks_are_different() throws Exception {
+        Invocation onDifferentMock = new InvocationBuilder().simpleMethod().mock("different mock").toInvocation();
+        assertFalse(simpleMethod.hasSimilarMethod(onDifferentMock));
+    }
+
+    @Test
+    public void should_not_be_similar_if_is_overloaded_but_used_with_the_same_arg() throws Exception {
+        Method method = IMethods.class.getMethod("simpleMethod", String.class);
+        Method overloadedMethod = IMethods.class.getMethod("simpleMethod", Object.class);
+
+        String sameArg = "test";
+
+        InvocationMatcher invocation = new InvocationBuilder().method(method).arg(sameArg).toInvocationMatcher();
+        Invocation overloadedInvocation = new InvocationBuilder().method(overloadedMethod).arg(sameArg).toInvocation();
+
+        assertFalse(invocation.hasSimilarMethod(overloadedInvocation));
+    }
+
+    @Test
+    public void should_be_similar_if_is_overloaded_but_used_with_different_arg() throws Exception {
+        Method method = IMethods.class.getMethod("simpleMethod", String.class);
+        Method overloadedMethod = IMethods.class.getMethod("simpleMethod", Object.class);
+
+        InvocationMatcher invocation = new InvocationBuilder().mock(mock).method(method).arg("foo").toInvocationMatcher();
+        Invocation overloadedInvocation = new InvocationBuilder().mock(mock).method(overloadedMethod).arg("bar").toInvocation();
+
+        assertTrue(invocation.hasSimilarMethod(overloadedInvocation));
+    }
+
+    @Test
+    public void should_capture_arguments_from_invocation() throws Exception {
+        //given
+        Invocation invocation = new InvocationBuilder().args("1", 100).toInvocation();
+        CapturingMatcher capturingMatcher = new CapturingMatcher();
+        InvocationMatcher invocationMatcher = new InvocationMatcher(invocation, (List) asList(new Equals("1"), capturingMatcher));
+
+        //when
+        invocationMatcher.captureArgumentsFrom(invocation);
+
+        //then
+        assertEquals(1, capturingMatcher.getAllValues().size());
+        assertEquals(100, capturingMatcher.getLastValue());
+    }
+
+    @Test
+    public void should_match_varargs_using_any_varargs() throws Exception {
+        //given
+        mock.varargs("1", "2");
+        Invocation invocation = getLastInvocation();
+        InvocationMatcher invocationMatcher = new InvocationMatcher(invocation, (List) asList(ANY));
+
+        //when
+        boolean match = invocationMatcher.matches(invocation);
+
+        //then
+        assertTrue(match);
+    }
+
+    @Test
+    public void should_capture_varargs_as_vararg() throws Exception {
+        //given
+        mock.mixedVarargs(1, "a", "b");
+        Invocation invocation = getLastInvocation();
+        CapturingMatcher m = new CapturingMatcher();
+        InvocationMatcher invocationMatcher = new InvocationMatcher(invocation, Arrays.<ArgumentMatcher>asList(new Equals(1), m));
+
+        //when
+        invocationMatcher.captureArgumentsFrom(invocation);
+
+        //then
+        Assertions.assertThat(m.getAllValues()).containsExactly("a", "b");
+    }
+
+    @Test  // like using several time the captor in the vararg
+    public void should_capture_arguments_when_args_count_does_NOT_match() throws Exception {
+        //given
+        mock.varargs();
+        Invocation invocation = getLastInvocation();
+
+        //when
+        InvocationMatcher invocationMatcher = new InvocationMatcher(invocation,(List) asList(ANY));
+
+        //then
+        invocationMatcher.captureArgumentsFrom(invocation);
+    }
+
+    @Test
+    public void should_create_from_invocations() throws Exception {
+        //given
+        Invocation i = new InvocationBuilder().toInvocation();
+        //when
+        List<InvocationMatcher> out = InvocationMatcher.createFrom(asList(i));
+        //then
+        assertEquals(1, out.size());
+        assertEquals(i, out.get(0).getInvocation());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/invocation/InvocationsFinderTest.java b/src/test/java/org/mockito/internal/invocation/InvocationsFinderTest.java
new file mode 100644
index 0000000..0121a24
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/InvocationsFinderTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.internal.verification.InOrderContextImpl;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertSame;
+import static junit.framework.TestCase.assertTrue;
+
+
+public class InvocationsFinderTest extends TestBase {
+
+    private LinkedList<Invocation> invocations = new LinkedList<Invocation>();
+    private Invocation simpleMethodInvocation;
+    private Invocation simpleMethodInvocationTwo;
+    private Invocation differentMethodInvocation;
+
+
+    private final InOrderContext context = new InOrderContextImpl();
+
+    @Mock private IMethods mock;
+
+    @Before
+    public void setup() throws Exception {
+        simpleMethodInvocation = new InvocationBuilder().mock(mock).simpleMethod().seq(1).toInvocation();
+        simpleMethodInvocationTwo = new InvocationBuilder().mock(mock).simpleMethod().seq(2).toInvocation();
+        differentMethodInvocation = new InvocationBuilder().mock(mock).differentMethod().seq(3).toInvocation();
+        invocations.addAll(Arrays.asList(simpleMethodInvocation, simpleMethodInvocationTwo, differentMethodInvocation));
+
+    }
+
+    @Test
+    public void shouldFindActualInvocations() throws Exception {
+        List<Invocation> actual = InvocationsFinder.findInvocations(invocations, new InvocationMatcher(simpleMethodInvocation));
+        Assertions.assertThat(actual).containsSequence(simpleMethodInvocation, simpleMethodInvocationTwo);
+
+        actual = InvocationsFinder.findInvocations(invocations, new InvocationMatcher(differentMethodInvocation));
+        Assertions.assertThat(actual).containsSequence(differentMethodInvocation);
+    }
+
+    @Test
+    public void shouldFindFirstUnverifiedInvocation() throws Exception {
+        assertSame(simpleMethodInvocation, InvocationsFinder.findFirstUnverified(invocations));
+
+        simpleMethodInvocationTwo.markVerified();
+        simpleMethodInvocation.markVerified();
+
+        assertSame(differentMethodInvocation, InvocationsFinder.findFirstUnverified(invocations));
+
+        differentMethodInvocation.markVerified();
+        assertNull(InvocationsFinder.findFirstUnverified(invocations));
+    }
+
+    @Test
+    public void shouldFindFirstUnverifiedInOrder() throws Exception {
+        //given
+        InOrderContextImpl context = new InOrderContextImpl();
+        assertSame(simpleMethodInvocation, InvocationsFinder.findFirstUnverifiedInOrder(context, invocations));
+
+        //when
+        context.markVerified(simpleMethodInvocationTwo);
+        context.markVerified(simpleMethodInvocation);
+
+        //then
+        assertSame(differentMethodInvocation, InvocationsFinder.findFirstUnverifiedInOrder(context, invocations));
+
+        //when
+        context.markVerified(differentMethodInvocation);
+
+        //then
+        assertNull(InvocationsFinder.findFirstUnverifiedInOrder(context, invocations));
+    }
+
+    @Test
+    public void shouldFindFirstUnverifiedInOrderAndRespectSequenceNumber() throws Exception {
+        //given
+        InOrderContextImpl context = new InOrderContextImpl();
+        assertSame(simpleMethodInvocation, InvocationsFinder.findFirstUnverifiedInOrder(context, invocations));
+
+        //when
+        //skipping verification of first invocation, then:
+        context.markVerified(simpleMethodInvocationTwo);
+        context.markVerified(differentMethodInvocation);
+
+        //then
+        assertSame(null, InvocationsFinder.findFirstUnverifiedInOrder(context, invocations));
+    }
+
+    @Test
+    public void shouldFindFirstUnverifiedInvocationOnMock() throws Exception {
+        assertSame(simpleMethodInvocation, InvocationsFinder.findFirstUnverified(invocations, simpleMethodInvocation.getMock()));
+        assertNull(InvocationsFinder.findFirstUnverified(invocations, "different mock"));
+    }
+
+    @Test
+    public void shouldFindFirstSimilarInvocationByName() throws Exception {
+        Invocation overloadedSimpleMethod = new InvocationBuilder().mock(mock).simpleMethod().arg("test").toInvocation();
+
+        Invocation found = InvocationsFinder.findSimilarInvocation(invocations, new InvocationMatcher(overloadedSimpleMethod));
+        assertSame(found, simpleMethodInvocation);
+    }
+
+    @Test
+    public void shouldFindInvocationWithTheSameMethod() throws Exception {
+        Invocation overloadedDifferentMethod = new InvocationBuilder().differentMethod().arg("test").toInvocation();
+
+        invocations.add(overloadedDifferentMethod);
+
+        Invocation found = InvocationsFinder.findSimilarInvocation(invocations, new InvocationMatcher(overloadedDifferentMethod));
+        assertSame(found, overloadedDifferentMethod);
+    }
+
+    @Test
+    public void shouldGetLastStackTrace() throws Exception {
+        Location last = InvocationsFinder.getLastLocation(invocations);
+        assertSame(differentMethodInvocation.getLocation(), last);
+
+        assertNull(InvocationsFinder.getLastLocation(Collections.<Invocation>emptyList()));
+    }
+
+    @Test
+    public void shouldFindAllMatchingUnverifiedChunks() throws Exception {
+        List<Invocation> allMatching = InvocationsFinder.findAllMatchingUnverifiedChunks(invocations, new InvocationMatcher(simpleMethodInvocation), context);
+        Assertions.assertThat(allMatching).containsSequence(simpleMethodInvocation, simpleMethodInvocationTwo);
+
+        context.markVerified(simpleMethodInvocation);
+        allMatching = InvocationsFinder.findAllMatchingUnverifiedChunks(invocations, new InvocationMatcher(simpleMethodInvocation), context);
+        Assertions.assertThat(allMatching).containsSequence(simpleMethodInvocationTwo);
+
+        context.markVerified(simpleMethodInvocationTwo);
+        allMatching = InvocationsFinder.findAllMatchingUnverifiedChunks(invocations, new InvocationMatcher(simpleMethodInvocation), context);
+        assertTrue(allMatching.isEmpty());
+    }
+
+    @Test
+    public void shouldFindMatchingChunk() throws Exception {
+        List<Invocation> chunk = InvocationsFinder.findMatchingChunk(invocations, new InvocationMatcher(simpleMethodInvocation), 2, context);
+        Assertions.assertThat(chunk).containsSequence(simpleMethodInvocation, simpleMethodInvocationTwo);
+    }
+
+    @Test
+    public void shouldReturnAllChunksWhenModeIsAtLeastOnce() throws Exception {
+        Invocation simpleMethodInvocationThree = new InvocationBuilder().mock(mock).toInvocation();
+        invocations.add(simpleMethodInvocationThree);
+
+        List<Invocation> chunk = InvocationsFinder.findMatchingChunk(invocations, new InvocationMatcher(simpleMethodInvocation), 1, context);
+        Assertions.assertThat(chunk).containsSequence(simpleMethodInvocation, simpleMethodInvocationTwo, simpleMethodInvocationThree);
+    }
+
+    @Test
+    public void shouldReturnAllChunksWhenWantedCountDoesntMatch() throws Exception {
+        Invocation simpleMethodInvocationThree = new InvocationBuilder().mock(mock).toInvocation();
+        invocations.add(simpleMethodInvocationThree);
+
+        List<Invocation> chunk = InvocationsFinder.findMatchingChunk(invocations, new InvocationMatcher(simpleMethodInvocation), 1, context);
+        Assertions.assertThat(chunk).containsSequence(simpleMethodInvocation, simpleMethodInvocationTwo, simpleMethodInvocationThree);
+    }
+
+    @Test
+    public void shouldFindPreviousInOrder() throws Exception {
+        Invocation previous = InvocationsFinder.findPreviousVerifiedInOrder(invocations, context);
+        assertNull(previous);
+
+        context.markVerified(simpleMethodInvocation);
+        context.markVerified(simpleMethodInvocationTwo);
+
+        previous = InvocationsFinder.findPreviousVerifiedInOrder(invocations, context);
+        assertSame(simpleMethodInvocationTwo, previous);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java b/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java
new file mode 100644
index 0000000..4f1f090
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.invocation.MatcherApplicationStrategy.getMatcherApplicationStrategyFor;
+import static org.mockito.internal.matchers.Any.ANY;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.internal.matchers.Any;
+import org.mockito.internal.matchers.Equals;
+import org.mockito.internal.matchers.InstanceOf;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+@SuppressWarnings("unchecked")
+public class MatcherApplicationStrategyTest extends TestBase {
+
+    @Mock
+    IMethods mock;
+    private Invocation invocation;
+    private List matchers;
+
+    private RecordingAction recordAction;
+
+    @Before
+    public void before() {
+        recordAction = new RecordingAction();
+    }
+
+    @Test
+    public void shouldKnowWhenActualArgsSizeIsDifferent1() {
+        // given
+        invocation = varargs("1");
+        matchers = asList(new Equals("1"));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(RETURN_ALWAYS_FALSE);
+
+        // then
+        assertFalse(match);
+    }
+
+    @Test
+    public void shouldKnowWhenActualArgsSizeIsDifferent2() {
+        // given
+        invocation = varargs("1");
+        matchers = asList(new Equals("1"));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(RETURN_ALWAYS_TRUE);
+
+        // then
+        assertTrue(match);
+    }
+
+    @Test
+    public void shouldKnowWhenActualArgsSizeIsDifferent() {
+        // given
+        invocation = varargs("1", "2");
+        matchers = asList(new Equals("1"));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(RETURN_ALWAYS_TRUE);
+
+        // then
+        assertFalse(match);
+    }
+
+    @Test
+    public void shouldKnowWhenMatchersSizeIsDifferent() {
+        // given
+        invocation = varargs("1");
+        matchers = asList(new Equals("1"), new Equals("2"));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(RETURN_ALWAYS_TRUE);
+
+        // then
+        assertFalse(match);
+    }
+
+    @Test
+    public void shouldKnowWhenVarargsMatch() {
+        // given
+        invocation = varargs("1", "2", "3");
+        matchers = asList(new Equals("1"), Any.ANY, new InstanceOf(String.class));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        assertTrue(match);
+    }
+
+    @Test
+    public void shouldAllowAnyVarargMatchEntireVararg() {
+        // given
+        invocation = varargs("1", "2");
+        matchers = asList(ANY);
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        assertTrue(match);
+    }
+
+    @Test
+    public void shouldNotAllowAnyObjectWithMixedVarargs() {
+        // given
+        invocation = mixedVarargs(1, "1", "2");
+        matchers = asList(new Equals(1));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        assertFalse(match);
+    }
+
+    @Test
+    public void shouldAllowAnyObjectWithMixedVarargs() {
+        // given
+        invocation = mixedVarargs(1, "1", "2");
+        matchers = asList(new Equals(1), ANY);
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        assertTrue(match);
+    }
+
+    @Test
+    public void shouldAnyObjectVarargDealWithDifferentSizeOfArgs() {
+        // given
+        invocation = mixedVarargs(1, "1", "2");
+        matchers = asList(new Equals(1));
+
+        // when
+        boolean match = getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        assertFalse(match);
+
+        recordAction.assertIsEmpty();
+    }
+
+    @Test
+    public void shouldMatchAnyVarargEvenIfOneOfTheArgsIsNull() {
+        // given
+        invocation = mixedVarargs(null, null, "2");
+        matchers = asList(new Equals(null), ANY);
+
+        // when
+        getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        recordAction.assertContainsExactly(new Equals(null), ANY, ANY);
+
+    }
+
+    @Test
+    public void shouldMatchAnyVarargEvenIfMatcherIsDecorated() {
+        // given
+        invocation = varargs("1", "2");
+        matchers = asList(ANY);
+
+        // when
+        getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        recordAction.assertContainsExactly(ANY, ANY);
+    }
+
+    private Invocation mixedVarargs(Object a, String... s) {
+        mock.mixedVarargs(a, s);
+        return getLastInvocation();
+    }
+
+    private Invocation varargs(String... s) {
+        mock.varargs(s);
+        return getLastInvocation();
+    }
+
+    private class RecordingAction implements ArgumentMatcherAction {
+        private List<ArgumentMatcher<?>> matchers = new ArrayList<ArgumentMatcher<?>>();
+
+        @Override
+        public boolean apply(ArgumentMatcher<?> matcher, Object argument) {
+            matchers.add(matcher);
+            return true;
+        }
+
+        public void assertIsEmpty() {
+            assertThat(matchers).isEmpty();
+        }
+
+        public void assertContainsExactly(ArgumentMatcher<?>... matchers) {
+            assertThat(this.matchers).containsExactly(matchers);
+        }
+    }
+
+    private static final ArgumentMatcherAction RETURN_ALWAYS_TRUE = new ArgumentMatcherAction() {
+        @Override
+        public boolean apply(ArgumentMatcher<?> matcher, Object argument) {
+            return true;
+        }
+    };
+
+    private static final ArgumentMatcherAction RETURN_ALWAYS_FALSE = new ArgumentMatcherAction() {
+        @Override
+        public boolean apply(ArgumentMatcher<?> matcher, Object argument) {
+            return false;
+        }
+    };
+
+}
diff --git a/src/test/java/org/mockito/internal/invocation/SerializableMethodTest.java b/src/test/java/org/mockito/internal/invocation/SerializableMethodTest.java
new file mode 100644
index 0000000..d320f25
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/SerializableMethodTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.*;
+
+
+public class SerializableMethodTest extends TestBase {
+
+    private MockitoMethod method;
+    private Method toStringMethod;
+    private Class<?>[] args;
+
+    @Before
+    public void createMethodToTestWith() throws SecurityException, NoSuchMethodException {
+        args = new Class<?>[0];
+        toStringMethod = this.getClass().getMethod("toString", args);
+        method = new SerializableMethod(toStringMethod);
+    }
+
+    @Test
+    public void shouldBeSerializable() throws Exception {
+        ByteArrayOutputStream serialized = new ByteArrayOutputStream();
+        new ObjectOutputStream(serialized).writeObject(method);
+    }
+
+    @Test
+    public void shouldBeAbleToRetrieveMethodExceptionTypes() throws Exception {
+        assertArrayEquals(toStringMethod.getExceptionTypes(), method.getExceptionTypes());
+    }
+
+    @Test
+    public void shouldBeAbleToRetrieveMethodName() throws Exception {
+        assertEquals(toStringMethod.getName(), method.getName());
+    }
+
+    @Test
+    public void shouldBeAbleToCheckIsArgVargs() throws Exception {
+        assertEquals(toStringMethod.isVarArgs(), method.isVarArgs());
+    }
+
+    @Test
+    public void shouldBeAbleToGetParameterTypes() throws Exception {
+        assertArrayEquals(toStringMethod.getParameterTypes(), method.getParameterTypes());
+    }
+
+    @Test
+    public void shouldBeAbleToGetReturnType() throws Exception {
+        assertEquals(toStringMethod.getReturnType(), method.getReturnType());
+    }
+
+    @Test
+    public void shouldBeEqualForTwoInstances() throws Exception {
+        assertTrue(new SerializableMethod(toStringMethod).equals(method));
+    }
+
+    @Test
+    public void shouldNotBeEqualForSameMethodFromTwoDifferentClasses() throws Exception {
+        Method testBaseToStringMethod = String.class.getMethod("toString", args);
+        assertFalse(new SerializableMethod(testBaseToStringMethod).equals(method));
+    }
+
+    //TODO: add tests for generated equals() method
+
+}
diff --git a/src/test/java/org/mockito/internal/invocation/TypeSafeMatchingTest.java b/src/test/java/org/mockito/internal/invocation/TypeSafeMatchingTest.java
new file mode 100644
index 0000000..40915ad
--- /dev/null
+++ b/src/test/java/org/mockito/internal/invocation/TypeSafeMatchingTest.java
@@ -0,0 +1,163 @@
+package org.mockito.internal.invocation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.invocation.TypeSafeMatching.matchesTypeSafe;
+
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.internal.matchers.LessOrEqual;
+import org.mockito.internal.matchers.Null;
+import org.mockito.internal.matchers.StartsWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+
+public class TypeSafeMatchingTest {
+
+    private static final Object NOT_A_COMPARABLE = new Object();
+
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    public IMethods mock;
+
+    /**
+     * Should not throw an {@link NullPointerException}
+     *
+     * @see Bug-ID https://github.com/mockito/mockito/issues/457
+     */
+    @Test
+    public void compareNullArgument() {
+        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(5), null);
+        assertThat(match).isFalse();
+
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToNonCompareable() {
+        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(5), NOT_A_COMPARABLE);
+        assertThat(match).isFalse();
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToNull() {
+        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(null), null);
+        assertThat(match).isFalse();
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToNull2() {
+        boolean match = matchesTypeSafe().apply(Null.NULL, null);
+        assertThat(match).isTrue();
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToStringVsInt() {
+        boolean match = matchesTypeSafe().apply(new StartsWith("Hello"), 123);
+        assertThat(match).isFalse();
+    }
+
+    @Test
+    public void compareToIntVsString() throws Exception {
+        boolean match = matchesTypeSafe().apply(new LessOrEqual<Integer>(5), "Hello");
+        assertThat(match).isFalse();
+    }
+
+    @Test
+    public void matchesOverloadsMustBeIgnored() {
+        class TestMatcher implements ArgumentMatcher<Integer> {
+            @Override
+            public boolean matches(Integer arg) {
+                return false;
+            }
+
+            @SuppressWarnings("unused")
+            public boolean matches(Date arg) {
+                throw new UnsupportedOperationException();
+            }
+
+            @SuppressWarnings("unused")
+            public boolean matches(Integer arg, Void v) {
+                throw new UnsupportedOperationException();
+            }
+
+        }
+
+        boolean match = matchesTypeSafe().apply(new TestMatcher(), 123);
+        assertThat(match).isFalse();
+    }
+
+    @Test
+    public void matchesWithSubTypeExtendingGenericClass() {
+        abstract class GenericMatcher<T> implements ArgumentMatcher<T> {
+        }
+        class TestMatcher extends GenericMatcher<Integer> {
+            @Override
+            public boolean matches(Integer argument) {
+                return true;
+            }
+        }
+        boolean match = matchesTypeSafe().apply(new TestMatcher(), 123);
+        assertThat(match).isTrue();
+    }
+
+    @Test
+    public void dontMatchesWithSubTypeExtendingGenericClass() {
+        final AtomicBoolean wasCalled = new AtomicBoolean();
+
+        abstract class GenericMatcher<T> implements ArgumentMatcher<T> {
+        }
+        class TestMatcher extends GenericMatcher<Integer> {
+            @Override
+            public boolean matches(Integer argument) {
+                wasCalled.set(true);
+                return true;
+            }
+        }
+        wasCalled.set(false);
+        matchesTypeSafe().apply(new TestMatcher(), 123);
+        assertThat(wasCalled.get()).isTrue();
+
+        wasCalled.set(false);
+        matchesTypeSafe().apply(new TestMatcher(), "");
+        assertThat(wasCalled.get()).isFalse();
+    }
+
+    @Test
+    public void passEveryArgumentTypeIfNoBridgeMethodWasGenerated() {
+        final AtomicBoolean wasCalled = new AtomicBoolean();
+        class GenericMatcher<T> implements ArgumentMatcher<T> {
+            @Override
+            public boolean matches(T argument) {
+                wasCalled.set(true);
+                return true;
+            }
+        }
+
+        wasCalled.set(false);
+        matchesTypeSafe().apply(new GenericMatcher<Integer>(), 123);
+        assertThat(wasCalled.get()).isTrue();
+
+        wasCalled.set(false);
+        matchesTypeSafe().apply(new GenericMatcher<Integer>(), "");
+        assertThat(wasCalled.get()).isTrue();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/junit/ArgMismatchFinderTest.java b/src/test/java/org/mockito/internal/junit/ArgMismatchFinderTest.java
new file mode 100644
index 0000000..aa2eecf
--- /dev/null
+++ b/src/test/java/org/mockito/internal/junit/ArgMismatchFinderTest.java
@@ -0,0 +1,127 @@
+package org.mockito.internal.junit;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+
+public class ArgMismatchFinderTest extends TestBase {
+
+    ArgMismatchFinder finder = new ArgMismatchFinder();
+    @Mock IMethods mock1;
+    @Mock IMethods mock2;
+
+    @Test
+    public void no_interactions() throws Exception {
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(0, mismatches.size());
+    }
+
+    @Test
+    public void no_mismatch_when_mock_different() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        mock2.simpleMethod(2); //arg mismatch on different mock
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(0, mismatches.size());
+    }
+
+    @Test
+    public void no_mismatch_when_method_different() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        mock1.otherMethod();
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(0, mismatches.size());
+    }
+
+    @Test
+    public void no_mismatch_when_stubbing_used() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        mock1.simpleMethod(1); // stub used
+        mock1.simpleMethod(2); // no stubbing, but we don't want it to be reported, either
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(0, mismatches.size());
+    }
+
+    @Test
+    public void stubbing_mismatch() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        mock1.simpleMethod(2);
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(1, mismatches.size());
+    }
+
+    @Test
+    public void single_mismatch_with_multiple_invocations() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        mock1.simpleMethod(2);
+        mock1.simpleMethod(3);
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(1, mismatches.size());
+        assertEquals("{mock1.simpleMethod(1);=[mock1.simpleMethod(2);, mock1.simpleMethod(3);]}", mismatches.toString());
+    }
+
+    @Test
+    public void single_invocation_with_multiple_stubs() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        when(mock1.simpleMethod(2)).thenReturn("2");
+        mock1.simpleMethod(3);
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(2, mismatches.size());
+        assertEquals("{mock1.simpleMethod(1);=[mock1.simpleMethod(3);], mock1.simpleMethod(2);=[mock1.simpleMethod(3);]}"
+                , mismatches.toString());
+    }
+
+    @Test
+    public void mismatch_reports_only_unstubbed_invocations() throws Exception {
+        //given
+        when(mock1.simpleMethod(1)).thenReturn("1"); //unused
+        when(mock1.simpleMethod(2)).thenReturn("2"); //used
+        mock1.simpleMethod(2); //stubbed
+        mock1.simpleMethod(3); //unstubbed
+
+        //when
+        StubbingArgMismatches mismatches = finder.getStubbingArgMismatches((List) asList(mock1, mock2));
+
+        //then
+        assertEquals("{mock1.simpleMethod(1);=[mock1.simpleMethod(3);]}", mismatches.toString());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/junit/ExceptionFactoryTest.java b/src/test/java/org/mockito/internal/junit/ExceptionFactoryTest.java
new file mode 100644
index 0000000..2dd54eb
--- /dev/null
+++ b/src/test/java/org/mockito/internal/junit/ExceptionFactoryTest.java
@@ -0,0 +1,54 @@
+package org.mockito.internal.junit;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockitoutil.ClassLoaders.excludingClassLoader;
+
+import java.lang.reflect.Method;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.exceptions.verification.ArgumentsAreDifferent;
+
+public class ExceptionFactoryTest {
+
+    private static ClassLoader classLoaderWithoutJUnit = excludingClassLoader().withCodeSourceUrlOf(ExceptionFactory.class).without("org.junit", "junit").build();
+
+    /** loaded by the current current class loader */
+    private static Class<?> junitArgumentsAreDifferent;
+
+    /** loaded by the custom classloader {@value #classLoaderWithoutJUnit}, which excludes junit-classes */
+    private static Class<?> nonJunitArgumentsAreDifferent;
+
+    @BeforeClass
+    public static void init() throws ClassNotFoundException {
+        nonJunitArgumentsAreDifferent = classLoaderWithoutJUnit.loadClass(ArgumentsAreDifferent.class.getName());
+        junitArgumentsAreDifferent = org.mockito.exceptions.verification.junit.ArgumentsAreDifferent.class;
+    }
+
+    @Test
+    public void createArgumentsAreDifferentException_withoutJUnit() throws Exception {
+        Class<?> exceptionFactory = classLoaderWithoutJUnit.loadClass(ExceptionFactory.class.getName());
+
+        Method m = exceptionFactory.getDeclaredMethod("createArgumentsAreDifferentException", String.class, String.class, String.class);
+        Object e = m.invoke(null, "message", "wanted", "actual");
+
+        assertThat(e).isExactlyInstanceOf(nonJunitArgumentsAreDifferent);
+    }
+
+    @Test
+    public void createArgumentsAreDifferentException_withJUnit() throws Exception {
+        AssertionError e = ExceptionFactory.createArgumentsAreDifferentException("message", "wanted", "actual");
+
+        assertThat(e).isExactlyInstanceOf(junitArgumentsAreDifferent);
+    }
+
+    @Test
+    public void createArgumentsAreDifferentException_withJUnit2x() throws Exception {
+        AssertionError e;
+
+        e = ExceptionFactory.createArgumentsAreDifferentException("message", "wanted", "actual");
+        assertThat(e).isExactlyInstanceOf(junitArgumentsAreDifferent);
+
+        e = ExceptionFactory.createArgumentsAreDifferentException("message", "wanted", "actual");
+        assertThat(e).isExactlyInstanceOf(junitArgumentsAreDifferent);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/junit/JUnitRuleTest.java b/src/test/java/org/mockito/internal/junit/JUnitRuleTest.java
new file mode 100644
index 0000000..8ae318b
--- /dev/null
+++ b/src/test/java/org/mockito/internal/junit/JUnitRuleTest.java
@@ -0,0 +1,47 @@
+package org.mockito.internal.junit;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.junit.MockitoJUnit;
+import org.mockitousage.IMethods;
+import org.mockitoutil.SafeJUnitRule;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mockingDetails;
+import static org.mockito.Mockito.when;
+
+public class JUnitRuleTest {
+
+    @Rule public SafeJUnitRule rule = new SafeJUnitRule(MockitoJUnit.rule());
+    @Mock IMethods mock;
+
+    @Test public void injects_into_test_case() throws Throwable {
+        assertTrue(mockingDetails(mock).isMock());
+    }
+
+    @Test
+    public void rethrows_exception() throws Throwable {
+        rule.expectFailure(RuntimeException.class, "foo");
+        throw new RuntimeException("foo");
+    }
+
+    @Test
+    public void detects_invalid_mockito_usage_on_success() throws Throwable {
+        rule.expectFailure(UnfinishedStubbingException.class);
+        when(mock.simpleMethod());
+    }
+
+    @Test
+    public void does_not_check_invalid_mockito_usage_on_failure() throws Throwable {
+        //This intended behavior is questionable
+        //However, it was like that since the beginning of JUnit rule support
+        //Users never questioned this behavior. Hence, let's stick to it unless we have more data
+        rule.expectFailure(RuntimeException.class, "foo");
+
+        Mockito.when(mock.simpleMethod()); // <--- unfinished stubbing
+        throw new RuntimeException("foo"); // <--- some failure
+    }
+}
diff --git a/src/test/java/org/mockito/internal/junit/StubbingArgMismatchesTest.java b/src/test/java/org/mockito/internal/junit/StubbingArgMismatchesTest.java
new file mode 100644
index 0000000..95b12ba
--- /dev/null
+++ b/src/test/java/org/mockito/internal/junit/StubbingArgMismatchesTest.java
@@ -0,0 +1,66 @@
+package org.mockito.internal.junit;
+
+import org.junit.Test;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockito.invocation.Invocation;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class StubbingArgMismatchesTest extends TestBase {
+
+    SimpleMockitoLogger logger = new SimpleMockitoLogger();
+    StubbingArgMismatches mismatches = new StubbingArgMismatches();
+
+    @Test
+    public void no_op_when_no_mismatches() throws Exception {
+        //when
+        mismatches.format("MyTest.myTestMethod", logger);
+
+        //then
+        assertTrue(logger.isEmpty());
+    }
+
+    @Test
+    public void logs_mismatch() throws Exception {
+        //given
+        mismatches.add(
+                new InvocationBuilder().args("a").location("-> at A.java").toInvocation(),
+                new InvocationBuilder().args("b").location("-> at B.java").toInvocation());
+
+        //when
+        mismatches.format("MyTest.myTestMethod", logger);
+
+        //then
+        assertEquals(
+            "[MockitoHint] MyTest.myTestMethod (see javadoc for MockitoHint):\n" +
+            "[MockitoHint] 1. Unused... -> at B.java\n" +
+            "[MockitoHint]  ...args ok? -> at A.java\n", logger.getLoggedInfo());
+    }
+
+    @Test
+    public void multiple_matching_invocations_per_stub_plus_some_other_invocation() throws Exception {
+        //given
+        Invocation stubbing = new InvocationBuilder().args("a").location("-> at A.java").toInvocation();
+        mismatches.add(new InvocationBuilder().args("x").location("-> at X.java").toInvocation(), stubbing);
+        mismatches.add(new InvocationBuilder().args("y").location("-> at Y.java").toInvocation(), stubbing);
+
+        mismatches.add(
+                new InvocationBuilder().method("differentMethod").args("n").location("-> at N.java").toInvocation(),
+                new InvocationBuilder().method("differentMethod").args("m").location("-> at M.java").toInvocation());
+
+        //when
+        mismatches.format("MyTest.myTestMethod", logger);
+
+        //then
+        assertEquals(
+            "[MockitoHint] MyTest.myTestMethod (see javadoc for MockitoHint):\n" +
+            "[MockitoHint] 1. Unused... -> at A.java\n" +
+            "[MockitoHint]  ...args ok? -> at X.java\n" +
+            "[MockitoHint]  ...args ok? -> at Y.java\n" +
+            "[MockitoHint] 2. Unused... -> at M.java\n" +
+            "[MockitoHint]  ...args ok? -> at N.java\n", logger.getLoggedInfo());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java b/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java
new file mode 100644
index 0000000..cfff121
--- /dev/null
+++ b/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java
@@ -0,0 +1,51 @@
+package org.mockito.internal.junit;
+
+import org.junit.Test;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.stubbing.StubbedInvocationMatcher;
+import org.mockito.internal.stubbing.answers.DoesNothing;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.internal.stubbing.answers.DoesNothing.doesNothing;
+
+public class UnusedStubbingsTest extends TestBase {
+
+    SimpleMockitoLogger logger = new SimpleMockitoLogger();
+
+    @Test
+    public void no_unused_stubbings() throws Exception {
+        //given
+        UnusedStubbings stubbings = new UnusedStubbings((List) asList());
+
+        //when
+        stubbings.format("MyTest.myTestMethod", logger);
+
+        //then
+        assertEquals("", logger.getLoggedInfo());
+    }
+
+    @Test
+    public void unused_stubbings() throws Exception {
+        //given
+        UnusedStubbings stubbings = new UnusedStubbings((List) asList(
+            new StubbedInvocationMatcher(new InvocationBuilder().toInvocationMatcher(), doesNothing()),
+            new StubbedInvocationMatcher(new InvocationBuilder().toInvocationMatcher(), doesNothing())
+        ));
+
+
+        //when
+        stubbings.format("MyTest.myTestMethod", logger);
+
+        //then
+        assertEquals(
+                "[MockitoHint] MyTest.myTestMethod (see javadoc for MockitoHint):\n" +
+                        "[MockitoHint] 1. Unused -> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
+                        "[MockitoHint] 2. Unused -> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n",
+                filterLineNo(logger.getLoggedInfo()));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/junit/util/JUnitFailureHackerTest.java b/src/test/java/org/mockito/internal/junit/util/JUnitFailureHackerTest.java
new file mode 100644
index 0000000..5fe771a
--- /dev/null
+++ b/src/test/java/org/mockito/internal/junit/util/JUnitFailureHackerTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit.util;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JUnitFailureHackerTest extends TestBase {
+
+    JUnitFailureHacker hacker = new JUnitFailureHacker();
+
+    @Test
+    public void shouldReplaceException() throws Exception {
+        //given
+        RuntimeException actualExc = new RuntimeException("foo");
+        Failure failure = new Failure(Description.EMPTY, actualExc);
+
+        //when
+        hacker.appendWarnings(failure, "unused stubbing");
+
+        //then
+        assertEquals(ExceptionIncludingMockitoWarnings.class, failure.getException().getClass());
+        assertEquals(actualExc, failure.getException().getCause());
+        Assertions.assertThat(actualExc.getStackTrace()).isEqualTo(failure.getException().getStackTrace());
+    }
+
+    @Test
+    public void shouldAppendWarning() throws Exception {
+        Failure failure = new Failure(Description.EMPTY, new RuntimeException("foo"));
+
+        //when
+        hacker.appendWarnings(failure, "unused stubbing blah");
+
+        //then
+        assertThat(failure.getException()).hasMessageContaining("unused stubbing blah");
+    }
+
+    @Test
+    public void shouldNotAppendWhenNoWarnings() throws Exception {
+        RuntimeException ex = new RuntimeException("foo");
+        Failure failure = new Failure(Description.EMPTY, ex);
+
+        //when
+        hacker.appendWarnings(failure, "");
+
+        //then
+        assertEquals(ex, failure.getException());
+    }
+
+    @Test
+    public void shouldNotAppendWhenNullWarnings() throws Exception {
+        RuntimeException ex = new RuntimeException("foo");
+        Failure failure = new Failure(Description.EMPTY, ex);
+
+        //when
+        hacker.appendWarnings(failure, null);
+
+        //then
+        assertEquals(ex, failure.getException());
+    }
+
+    @Test
+    public void shouldPrintTheWarningSoICanSeeIt() throws Exception {
+        Failure failure = new Failure(Description.EMPTY, new RuntimeException("foo"));
+
+        //when
+        hacker.appendWarnings(failure, "unused stubbing blah");
+
+        //then
+        System.out.println(failure.getException());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/CapturingMatcherTest.java b/src/test/java/org/mockito/internal/matchers/CapturingMatcherTest.java
new file mode 100644
index 0000000..5a9cf44
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/CapturingMatcherTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class CapturingMatcherTest extends TestBase {
+
+    @Test
+    public void should_capture_arguments() throws Exception {
+        //given
+        CapturingMatcher<String> m = new CapturingMatcher<String>();
+
+        //when
+        m.captureFrom("foo");
+        m.captureFrom("bar");
+
+        //then
+        Assertions.assertThat(m.getAllValues()).containsSequence("foo", "bar");
+    }
+
+    @Test
+    public void should_know_last_captured_value() throws Exception {
+        //given
+        CapturingMatcher<String> m = new CapturingMatcher<String>();
+
+        //when
+        m.captureFrom("foo");
+        m.captureFrom("bar");
+
+        //then
+        assertEquals("bar", m.getLastValue());
+    }
+
+    @Test
+    public void should_scream_when_nothing_yet_captured() throws Exception {
+        //given
+        CapturingMatcher<String> m = new CapturingMatcher<String>();
+
+        try {
+            //when
+            m.getLastValue();
+            //then
+            fail();
+        } catch (MockitoException e) {}
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/ComparableMatchersTest.java b/src/test/java/org/mockito/internal/matchers/ComparableMatchersTest.java
new file mode 100644
index 0000000..4694b79
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/ComparableMatchersTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.math.BigDecimal;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+public class ComparableMatchersTest extends TestBase {
+
+    @Test
+    public void testLessThan() {
+        test(new LessThan<String>("b"), true, false, false, "lt");
+    }
+
+    @Test
+    public void testGreaterThan() {
+        test(new GreaterThan<String>("b"), false, true, false, "gt");
+    }
+
+    @Test
+    public void testLessOrEqual() {
+        test(new LessOrEqual<String>("b"), true, false, true, "leq");
+    }
+
+    @Test
+    public void testGreaterOrEqual() {
+        test(new GreaterOrEqual<String>("b"), false, true, true, "geq");
+    }
+
+    @Test
+    public void testCompareEqual() {
+        test(new CompareEqual<String>("b"), false, false, true, "cmpEq");
+
+        // Make sure it works when equals provide a different result than compare
+        CompareEqual<BigDecimal> cmpEq = new CompareEqual<BigDecimal>(new BigDecimal("5.00"));
+        assertTrue(cmpEq.matches(new BigDecimal("5")));
+    }
+
+    private void test(CompareTo<String> compareTo, boolean lower, boolean higher,
+            boolean equals, String name) {
+
+        assertEquals(lower, compareTo.matches("a"));
+        assertEquals(equals, compareTo.matches("b"));
+        assertEquals(higher, compareTo.matches("c"));
+
+        assertEquals(name + "(b)", compareTo.toString());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/EqualityTest.java b/src/test/java/org/mockito/internal/matchers/EqualityTest.java
new file mode 100644
index 0000000..b0ddfc2
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/EqualityTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.internal.matchers.Equality.areEqual;
+
+public class EqualityTest extends TestBase {
+
+    @Test
+    public void shouldKnowIfObjectsAreEqual() throws Exception {
+        int[] arr = new int[] {1, 2};
+        assertTrue(areEqual(arr, arr));
+        assertTrue(areEqual(new int[] {1, 2}, new int[] {1, 2}));
+        assertTrue(areEqual(new Double[] {1.0}, new Double[] {1.0}));
+        assertTrue(areEqual(new String[0], new String[0]));
+        assertTrue(areEqual(new Object[10], new Object[10]));
+        assertTrue(areEqual(new int[] {1}, new Integer[] {1}));
+        assertTrue(areEqual(new Object[] {"1"}, new String[] {"1"}));
+        Object badequals=new BadEquals();
+        assertTrue(areEqual(badequals,badequals));
+
+        assertFalse(areEqual(new Object[9], new Object[10]));
+        assertFalse(areEqual(new int[] {1, 2}, new int[] {1}));
+        assertFalse(areEqual(new int[] {1}, new double[] {1.0}));
+    }
+
+    private final class BadEquals {
+        @Override
+        public boolean equals(Object oth) {
+            throw new RuntimeException();
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/EqualsTest.java b/src/test/java/org/mockito/internal/matchers/EqualsTest.java
new file mode 100644
index 0000000..3e94d41
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/EqualsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+
+
+public class EqualsTest extends TestBase {
+
+    @Test
+    public void shouldBeEqual() {
+        assertEquals(new Equals(null), new Equals(null));
+        assertEquals(new Equals(new Integer(2)), new Equals(new Integer(2)));
+        assertFalse(new Equals(null).equals(null));
+        assertFalse(new Equals(null).equals("Test"));
+        assertEquals(1, new Equals(null).hashCode());
+    }
+
+    @Test
+    public void shouldArraysBeEqual() {
+        assertTrue(new Equals(new int[] {1, 2}).matches(new int[] {1, 2}));
+        assertFalse(new Equals(new Object[] {"1"}).matches(new Object[] {"1.0"}));
+    }
+
+    @Test
+    public void shouldDescribeWithExtraTypeInfo() throws Exception {
+        String descStr = new Equals(100).toStringWithType();
+
+        assertEquals("(Integer) 100", descStr);
+    }
+
+    @Test
+    public void shouldDescribeWithExtraTypeInfoOfLong() throws Exception {
+        String descStr = new Equals(100L).toStringWithType();
+
+        assertEquals("(Long) 100L", descStr);
+    }
+
+    @Test
+    public void shouldDescribeWithTypeOfString() throws Exception {
+        String descStr = new Equals("x").toStringWithType();
+
+        assertEquals("(String) \"x\"", descStr);
+    }
+
+    @Test
+    public void shouldAppendQuotingForString() {
+        String descStr = new Equals("str").toString();
+
+        assertEquals("\"str\"", descStr);
+    }
+
+    @Test
+    public void shouldAppendQuotingForChar() {
+        String descStr = new Equals('s').toString();
+
+        assertEquals("'s'", descStr);
+    }
+
+    @Test
+    public void shouldDescribeUsingToString() {
+        String descStr = new Equals(100).toString();
+
+        assertEquals("100", descStr);
+    }
+
+    @Test
+    public void shouldDescribeNull() {
+        String descStr = new Equals(null).toString();
+
+        assertEquals("null", descStr);
+    }
+
+    @Test
+    public void shouldMatchTypes() throws Exception {
+        //when
+        ContainsExtraTypeInfo equals = new Equals(10);
+
+        //then
+        assertTrue(equals.typeMatches(10));
+        assertFalse(equals.typeMatches(10L));
+    }
+
+    @Test
+    public void shouldMatchTypesSafelyWhenActualIsNull() throws Exception {
+        //when
+        ContainsExtraTypeInfo equals = new Equals(null);
+
+        //then
+        assertFalse(equals.typeMatches(10));
+    }
+
+    @Test
+    public void shouldMatchTypesSafelyWhenGivenIsNull() throws Exception {
+        //when
+        ContainsExtraTypeInfo equals = new Equals(10);
+
+        //then
+        assertFalse(equals.typeMatches(null));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/InstanceOfTest.java b/src/test/java/org/mockito/internal/matchers/InstanceOfTest.java
new file mode 100644
index 0000000..0fb603c
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/InstanceOfTest.java
@@ -0,0 +1,64 @@
+package org.mockito.internal.matchers;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class InstanceOfTest {
+
+    @Test
+    public void should_describe_the_matcher() {
+        assertThat(new InstanceOf(Object.class).toString()).contains("isA")
+                                                           .contains("Object");
+        assertThat(new InstanceOf(Object[].class).toString()).contains("isA")
+                                                           .contains("Object[]");
+        assertThat(new InstanceOf(Object.class, "matches something").toString()).isEqualTo("matches something");
+    }
+
+    @Test
+    public void should_check_instance_type() {
+        assertThat(new InstanceOf(Object.class).matches(new Object())).isTrue();
+        assertThat(new InstanceOf(Object.class).matches(new ArrayList())).isTrue();
+        assertThat(new InstanceOf(List.class).matches(new ArrayList())).isTrue();
+        assertThat(new InstanceOf(List.class).matches(new Object())).isFalse();
+    }
+
+    @Test
+    public void should_check_for_primitive_wrapper_types() {
+        assertThat(new InstanceOf(int.class).matches(1000)).isTrue();
+        assertThat(new InstanceOf(Integer.class).matches(1000)).isTrue();
+        assertThat(new InstanceOf(int.class).matches(new Integer(1000))).isTrue();
+        assertThat(new InstanceOf(Integer.class).matches(new Integer(1000))).isTrue();
+
+        assertThat(new InstanceOf(double.class).matches(1000.1)).isTrue();
+        assertThat(new InstanceOf(Double.class).matches(1000.1)).isTrue();
+        assertThat(new InstanceOf(double.class).matches(new Double(1000.1))).isTrue();
+        assertThat(new InstanceOf(Double.class).matches(new Double(1000.1))).isTrue();
+
+        assertThat(new InstanceOf(int.class).matches(1000L)).isFalse();
+        assertThat(new InstanceOf(Integer.class).matches(1000L)).isFalse();
+        assertThat(new InstanceOf(int.class).matches(new Long(1000))).isFalse();
+        assertThat(new InstanceOf(Integer.class).matches(new Long(1000))).isFalse();
+
+        assertThat(new InstanceOf(long.class).matches(1000L)).isTrue();
+        assertThat(new InstanceOf(Long.class).matches(1000L)).isTrue();
+        assertThat(new InstanceOf(long.class).matches(new Long(1000))).isTrue();
+        assertThat(new InstanceOf(Long.class).matches(new Long(1000))).isTrue();
+
+        assertThat(new InstanceOf(long.class).matches(1000)).isFalse();
+        assertThat(new InstanceOf(Long.class).matches(1000)).isFalse();
+        assertThat(new InstanceOf(long.class).matches(new Integer(1000))).isFalse();
+        assertThat(new InstanceOf(Long.class).matches(new Integer(1000))).isFalse();
+    }
+
+    @Test
+    public void can_be_vararg_aware() {
+        assertThat(new InstanceOf.VarArgAware(Number[].class)).isInstanceOf(VarargMatcher.class);
+        assertThat(new InstanceOf.VarArgAware(Number[].class).matches(new Integer[0])).isTrue();
+        assertThat(new InstanceOf.VarArgAware(Number[].class).matches(new Number[0])).isTrue();
+        assertThat(new InstanceOf.VarArgAware(Number[].class).matches(new Object[0])).isFalse();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/MatchersPrinterTest.java b/src/test/java/org/mockito/internal/matchers/MatchersPrinterTest.java
new file mode 100644
index 0000000..857e229
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/MatchersPrinterTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import org.junit.Test;
+import org.mockito.internal.matchers.text.MatchersPrinter;
+import org.mockito.internal.reporting.PrintSettings;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+
+@SuppressWarnings("unchecked")
+public class MatchersPrinterTest extends TestBase {
+
+    private final MatchersPrinter printer = new MatchersPrinter();
+
+    @Test
+    public void shouldGetArgumentsLine() {
+        String line = printer.getArgumentsLine((List) Arrays.asList(new Equals(1), new Equals(2)), new PrintSettings());
+        assertEquals("(1, 2);", line);
+    }
+
+    @Test
+    public void shouldGetArgumentsBlock() {
+        String line = printer.getArgumentsBlock((List) Arrays.asList(new Equals(1), new Equals(2)), new PrintSettings());
+        assertEquals("(\n    1,\n    2\n);", line);
+    }
+
+    @Test
+    public void shouldDescribeTypeInfoOnlyMarkedMatchers() {
+        //when
+        String line = printer.getArgumentsLine((List) Arrays.asList(new Equals(1L), new Equals(2)), PrintSettings.verboseMatchers(1));
+        //then
+        assertEquals("(1L, (Integer) 2);", line);
+    }
+
+    @Test
+    public void shouldDescribeStringMatcher() {
+        //when
+        String line = printer.getArgumentsLine((List) Arrays.asList(new Equals(1L), new Equals("x")), PrintSettings.verboseMatchers(1));
+        //then
+        assertEquals("(1L, (String) \"x\");", line);
+    }
+
+    @Test
+    public void shouldGetVerboseArgumentsInBlock() {
+        //when
+        String line = printer.getArgumentsBlock((List) Arrays.asList(new Equals(1L), new Equals(2)), PrintSettings.verboseMatchers(0, 1));
+        //then
+        assertEquals("(\n    (Long) 1L,\n    (Integer) 2\n);", line);
+    }
+
+    @Test
+    public void shouldGetVerboseArgumentsEvenIfSomeMatchersAreNotVerbose() {
+        //when
+        String line = printer.getArgumentsLine((List) Arrays.asList(new Equals(1L), NotNull.NOT_NULL), PrintSettings.verboseMatchers(0));
+        //then
+        assertEquals("((Long) 1L, notNull());", line);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java b/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java
new file mode 100644
index 0000000..9611dee
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/MatchersToStringTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.util.regex.Pattern;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class MatchersToStringTest extends TestBase {
+
+    @Test
+    public void sameToStringWithString() {
+        assertEquals("same(\"X\")", new Same("X").toString());
+    }
+
+    @Test
+    public void nullToString() {
+        assertEquals("isNull()", Null.NULL.toString());
+    }
+
+    @Test
+    public void notNullToString() {
+        assertEquals("notNull()", NotNull.NOT_NULL.toString());
+    }
+
+    @Test
+    public void anyToString() {
+        assertEquals("<any>", Any.ANY.toString());
+    }
+
+    @Test
+    public void sameToStringWithChar() {
+        assertEquals("same('x')", new Same('x').toString());
+    }
+
+    @Test
+    public void sameToStringWithObject() {
+        Object o = new Object() {
+            @Override
+            public String toString() {
+                return "X";
+            }
+        };
+        assertEquals("same(X)", new Same(o).toString());
+    }
+
+    @Test
+    public void equalsToStringWithString() {
+        assertEquals("\"X\"", new Equals("X").toString());
+
+    }
+
+    @Test
+    public void equalsToStringWithChar() {
+        assertEquals("'x'", new Equals('x').toString());
+    }
+
+    @Test
+    public void equalsToStringWithObject() {
+        Object o = new Object() {
+            @Override
+            public String toString() {
+                return "X";
+            }
+        };
+        assertEquals("X", new Equals(o).toString());
+    }
+
+    @Test
+    public void orToString() {
+        ArgumentMatcher<?> m1=new Equals(1);
+        ArgumentMatcher<?> m2=new Equals(2);
+        assertEquals("or(1, 2)", new Or(m1,m2).toString());
+    }
+
+    @Test
+    public void notToString() {
+        assertEquals("not(1)", new Not(new Equals(1)).toString());
+    }
+
+    @Test
+    public void andToString() {
+        ArgumentMatcher<?> m1=new Equals(1);
+        ArgumentMatcher<?> m2=new Equals(2);
+        assertEquals("and(1, 2)", new And(m1,m2).toString());
+    }
+
+    @Test
+    public void startsWithToString() {
+        assertEquals("startsWith(\"AB\")", new StartsWith("AB").toString());
+    }
+
+    @Test
+    public void endsWithToString() {
+        assertEquals("endsWith(\"AB\")", new EndsWith("AB").toString());
+    }
+
+    @Test
+    public void containsToString() {
+        assertEquals("contains(\"AB\")", new Contains("AB").toString());
+    }
+
+    @Test
+    public void findToString() {
+        assertEquals("find(\"\\\\s+\")", new Find("\\s+").toString());
+    }
+
+    @Test
+    public void matchesToString() {
+        assertEquals("matches(\"\\\\s+\")", new Matches("\\s+").toString());
+        assertEquals("matches(\"\\\\s+\")", new Matches(Pattern.compile("\\s+")).toString());
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/matchers/StringMatchersTest.java b/src/test/java/org/mockito/internal/matchers/StringMatchersTest.java
new file mode 100644
index 0000000..ff42395
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/StringMatchersTest.java
@@ -0,0 +1,73 @@
+package org.mockito.internal.matchers;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for the Matchers that operate over strings
+ */
+public class StringMatchersTest {
+	@Test
+	public void startsWithString() {
+		assertTrue(new StartsWith("mockito").matches("mockito is here"));
+	}
+
+	@Test
+	public void doesNotStartWithString() {
+		assertFalse(new StartsWith("junit").matches("mockito is here"));
+	}
+
+	@Test
+	public void nullStartsWith() {
+		assertFalse(new StartsWith("java").matches(null));
+	}
+
+	@Test
+	public void endsWithString() {
+		assertTrue(new EndsWith("mockito").matches("here is mockito"));
+	}
+
+	@Test
+	public void doesNotEndWithString() {
+		assertFalse(new EndsWith("junit").matches("here is mockito"));
+	}
+
+	@Test
+	public void nullEndsWith() {
+		assertFalse(new EndsWith("java").matches(null));
+	}
+
+	@Test
+	public void containsString() {
+		assertTrue(new Contains("mockito").matches("****mockito****"));
+	}
+
+	@Test
+	public void stringDoesNotContain() {
+		assertFalse(new Contains("junit").matches("****mockito****"));
+	}
+
+	@Test
+	public void nullContainsNothing() {
+		assertFalse(new Contains("mockito").matches(null));
+	}
+
+	@Test
+	public void matchesRegex() {
+		assertTrue(new Find("eleph.nt").matches("the elephant in the room"));
+		assertTrue(new Find("eleph.nt").matches("the elephInt in the room"));
+	}
+
+	@Test
+	public void doesNotMatchRegex() {
+		assertFalse(new Find("eleph.nt").matches("the otter in the room"));
+	}
+
+	@Test
+	public void nullDoesNotMatchRegex() {
+		assertFalse(new Find("eleph.nt").matches(null));
+	}
+
+}
diff --git a/src/test/java/org/mockito/internal/matchers/apachecommons/EqualsBuilderTest.java b/src/test/java/org/mockito/internal/matchers/apachecommons/EqualsBuilderTest.java
new file mode 100644
index 0000000..a825bc0
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/apachecommons/EqualsBuilderTest.java
@@ -0,0 +1,996 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+//Class comes from Apache Commons Lang, added some tiny changes
+package org.mockito.internal.matchers.apachecommons;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+
+import static junit.framework.TestCase.*;
+
+/**
+ * @author <a href="mailto:sdowney@panix.com">Steve Downey</a>
+ * @author <a href="mailto:scolebourne@joda.org">Stephen Colebourne</a>
+ * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
+ * @author Maarten Coene
+ * @version $Id: EqualsBuilderTest.java 611543 2008-01-13 07:00:22Z bayard $
+ */
+public class EqualsBuilderTest extends TestBase {
+
+    @Test
+    public void testname() throws Exception {
+
+    }
+
+    static class TestObject {
+        private int a;
+        public TestObject() {
+        }
+        public TestObject(int a) {
+            this.a = a;
+        }
+        public boolean equals(Object o) {
+            if (o == null) { return false; }
+            if (o == this) { return true; }
+            if (o.getClass() != getClass()) {
+                return false;
+            }
+
+            TestObject rhs = (TestObject) o;
+            return (a == rhs.a);
+        }
+        public int hashCode() {
+            return super.hashCode();
+        }
+
+        public void setA(int a) {
+            this.a = a;
+        }
+
+        public int getA() {
+            return a;
+        }
+    }
+
+    static class TestSubObject extends TestObject {
+        private int b;
+        public TestSubObject() {
+            super(0);
+        }
+        public TestSubObject(int a, int b) {
+            super(a);
+            this.b = b;
+        }
+        public boolean equals(Object o) {
+            if (o == null) { return false; }
+            if (o == this) { return true; }
+            if (o.getClass() != getClass()) {
+                return false;
+            }
+
+            TestSubObject rhs = (TestSubObject) o;
+            return super.equals(o) && (b == rhs.b);
+        }
+        public int hashCode() {
+            return 1;
+        }
+
+        public void setB(int b) {
+            this.b = b;
+        }
+
+        public int getB() {
+            return b;
+        }
+    }
+
+    static class TestEmptySubObject extends TestObject {
+        public TestEmptySubObject(int a) {
+            super(a);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    static class TestTSubObject extends TestObject {
+        private transient int t;
+        public TestTSubObject(int a, int t) {
+            super(a);
+            this.t = t;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    static class TestTTSubObject extends TestTSubObject {
+        private transient int tt;
+        public TestTTSubObject(int a, int t, int tt) {
+            super(a, t);
+            this.tt = tt;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    static class TestTTLeafObject extends TestTTSubObject {
+        private int leafValue;
+        public TestTTLeafObject(int a, int t, int tt, int leafValue) {
+            super(a, t, tt);
+            this.leafValue = leafValue;
+        }
+    }
+
+    static class TestTSubObject2 extends TestObject {
+        private transient int t;
+        public TestTSubObject2(int a, int t) {
+            super(a);
+        }
+        public int getT() {
+            return t;
+        }
+        public void setT(int t) {
+            this.t = t;
+        }
+    }
+
+    @Test public void testReflectionEquals() {
+        TestObject o1 = new TestObject(4);
+        TestObject o2 = new TestObject(5);
+        assertTrue(EqualsBuilder.reflectionEquals(o1, o1));
+        assertTrue(!EqualsBuilder.reflectionEquals(o1, o2));
+        o2.setA(4);
+        assertTrue(EqualsBuilder.reflectionEquals(o1, o2));
+
+        assertTrue(!EqualsBuilder.reflectionEquals(o1, this));
+
+        assertTrue(!EqualsBuilder.reflectionEquals(o1, null));
+        assertTrue(!EqualsBuilder.reflectionEquals(null, o2));
+        assertTrue(EqualsBuilder.reflectionEquals((Object) null, (Object) null));
+    }
+
+    @Test public void testReflectionHierarchyEquals() {
+        testReflectionHierarchyEquals(false);
+        testReflectionHierarchyEquals(true);
+        // Transients
+        assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true));
+        assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), false));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 0, 0, 4), new TestTTLeafObject(1, 2, 3, 4), true));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 0), true));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(0, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true));
+    }
+
+  private void testReflectionHierarchyEquals(boolean testTransients) {
+        TestObject to1 = new TestObject(4);
+        TestObject to1Bis = new TestObject(4);
+        TestObject to1Ter = new TestObject(4);
+        TestObject to2 = new TestObject(5);
+        TestEmptySubObject teso = new TestEmptySubObject(4);
+        TestTSubObject ttso = new TestTSubObject(4, 1);
+        TestTTSubObject tttso = new TestTTSubObject(4, 1, 2);
+        TestTTLeafObject ttlo = new TestTTLeafObject(4, 1, 2, 3);
+        TestSubObject tso1 = new TestSubObject(1, 4);
+        TestSubObject tso1bis = new TestSubObject(1, 4);
+        TestSubObject tso1ter = new TestSubObject(1, 4);
+        TestSubObject tso2 = new TestSubObject(2, 5);
+
+        testReflectionEqualsEquivalenceRelationship(to1, to1Bis, to1Ter, to2, new TestObject(), testTransients);
+        testReflectionEqualsEquivalenceRelationship(tso1, tso1bis, tso1ter, tso2, new TestSubObject(), testTransients);
+
+        // More sanity checks:
+
+        // same values
+        assertTrue(EqualsBuilder.reflectionEquals(ttlo, ttlo, testTransients));
+        assertTrue(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 10), testTransients));
+        // same super values, diff sub values
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 11), testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 11), new TestSubObject(1, 10), testTransients));
+        // diff super values, same sub values
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestSubObject(1, 10), testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(0, 10), testTransients));
+
+        // mix super and sub types: equals
+        assertTrue(EqualsBuilder.reflectionEquals(to1, teso, testTransients));
+        assertTrue(EqualsBuilder.reflectionEquals(teso, to1, testTransients));
+
+        assertTrue(EqualsBuilder.reflectionEquals(to1, ttso, false)); // Force testTransients = false for this assert
+        assertTrue(EqualsBuilder.reflectionEquals(ttso, to1, false)); // Force testTransients = false for this assert
+
+        assertTrue(EqualsBuilder.reflectionEquals(to1, tttso, false)); // Force testTransients = false for this assert
+        assertTrue(EqualsBuilder.reflectionEquals(tttso, to1, false)); // Force testTransients = false for this assert
+
+        assertTrue(EqualsBuilder.reflectionEquals(ttso, tttso, false)); // Force testTransients = false for this assert
+        assertTrue(EqualsBuilder.reflectionEquals(tttso, ttso, false)); // Force testTransients = false for this assert
+
+        // mix super and sub types: NOT equals
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(0), new TestEmptySubObject(1), testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestEmptySubObject(1), new TestObject(0), testTransients));
+
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(0), new TestTSubObject(1, 1), testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestTSubObject(1, 1), new TestObject(0), testTransients));
+
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(1), new TestSubObject(0, 10), testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestObject(1), testTransients));
+
+        assertTrue(!EqualsBuilder.reflectionEquals(to1, ttlo));
+        assertTrue(!EqualsBuilder.reflectionEquals(tso1, this));
+    }
+
+    /**
+     * Equivalence relationship tests inspired by "Effective Java":
+     * <ul>
+     * <li>reflection</li>
+     * <li>symmetry</li>
+     * <li>transitive</li>
+     * <li>consistency</li>
+     * <li>non-null reference</li>
+     * </ul>
+     * @param to a TestObject
+     * @param toBis a TestObject, equal to to and toTer
+     * @param toTer Left hand side, equal to to and toBis
+     * @param to2 a different TestObject
+     * @param oToChange a TestObject that will be changed
+     */
+    private void testReflectionEqualsEquivalenceRelationship(
+        TestObject to,
+        TestObject toBis,
+        TestObject toTer,
+        TestObject to2,
+        TestObject oToChange,
+        boolean testTransients) {
+
+        // reflection test
+        assertTrue(EqualsBuilder.reflectionEquals(to, to, testTransients));
+        assertTrue(EqualsBuilder.reflectionEquals(to2, to2, testTransients));
+
+        // symmetry test
+        assertTrue(EqualsBuilder.reflectionEquals(to, toBis, testTransients) && EqualsBuilder.reflectionEquals(toBis, to, testTransients));
+
+        // transitive test
+        assertTrue(
+            EqualsBuilder.reflectionEquals(to, toBis, testTransients)
+                && EqualsBuilder.reflectionEquals(toBis, toTer, testTransients)
+                && EqualsBuilder.reflectionEquals(to, toTer, testTransients));
+
+        // consistency test
+        oToChange.setA(to.getA());
+        if (oToChange instanceof TestSubObject) {
+            ((TestSubObject) oToChange).setB(((TestSubObject) to).getB());
+        }
+        assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+        assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+        oToChange.setA(to.getA() + 1);
+        if (oToChange instanceof TestSubObject) {
+            ((TestSubObject) oToChange).setB(((TestSubObject) to).getB() + 1);
+        }
+        assertTrue(!EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+
+        // non-null reference test
+        assertTrue(!EqualsBuilder.reflectionEquals(to, null, testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(to2, null, testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(null, to, testTransients));
+        assertTrue(!EqualsBuilder.reflectionEquals(null, to2, testTransients));
+        assertTrue(EqualsBuilder.reflectionEquals((Object) null, (Object) null, testTransients));
+    }
+
+    @Test public void testSuper() {
+        TestObject o1 = new TestObject(4);
+        TestObject o2 = new TestObject(5);
+        assertEquals(true, new EqualsBuilder().appendSuper(true).append(o1, o1).isEquals());
+        assertEquals(false, new EqualsBuilder().appendSuper(false).append(o1, o1).isEquals());
+        assertEquals(false, new EqualsBuilder().appendSuper(true).append(o1, o2).isEquals());
+        assertEquals(false, new EqualsBuilder().appendSuper(false).append(o1, o2).isEquals());
+    }
+
+    @Test public void testObject() {
+        TestObject o1 = new TestObject(4);
+        TestObject o2 = new TestObject(5);
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+        o2.setA(4);
+        assertTrue(new EqualsBuilder().append(o1, o2).isEquals());
+
+        assertTrue(!new EqualsBuilder().append(o1, this).isEquals());
+
+        assertTrue(!new EqualsBuilder().append(o1, null).isEquals());
+        assertTrue(!new EqualsBuilder().append(null, o2).isEquals());
+        assertTrue(new EqualsBuilder().append((Object) null, (Object) null).isEquals());
+    }
+
+    @Test public void testLong() {
+        long o1 = 1L;
+        long o2 = 2L;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testInt() {
+        int o1 = 1;
+        int o2 = 2;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testShort() {
+        short o1 = 1;
+        short o2 = 2;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testChar() {
+        char o1 = 1;
+        char o2 = 2;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testByte() {
+        byte o1 = 1;
+        byte o2 = 2;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testDouble() {
+        double o1 = 1;
+        double o2 = 2;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, Double.NaN).isEquals());
+        assertTrue(new EqualsBuilder().append(Double.NaN, Double.NaN).isEquals());
+        assertTrue(new EqualsBuilder().append(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isEquals());
+    }
+
+    @Test public void testFloat() {
+        float o1 = 1;
+        float o2 = 2;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, Float.NaN).isEquals());
+        assertTrue(new EqualsBuilder().append(Float.NaN, Float.NaN).isEquals());
+        assertTrue(new EqualsBuilder().append(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY).isEquals());
+    }
+
+    // https://issues.apache.org/jira/browse/LANG-393
+    @Test public void testBigDecimal() {
+        BigDecimal o1 = new BigDecimal("2.0");
+        BigDecimal o2 = new BigDecimal("2.00");
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testAccessors() {
+        EqualsBuilder equalsBuilder = new EqualsBuilder();
+        assertTrue(equalsBuilder.isEquals());
+        equalsBuilder.setEquals(true);
+        assertTrue(equalsBuilder.isEquals());
+        equalsBuilder.setEquals(false);
+        assertFalse(equalsBuilder.isEquals());
+    }
+
+    @Test public void testBoolean() {
+        boolean o1 = true;
+        boolean o2 = false;
+        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+    }
+
+    @Test public void testObjectArray() {
+        TestObject[] obj1 = new TestObject[3];
+        obj1[0] = new TestObject(4);
+        obj1[1] = new TestObject(5);
+        obj1[2] = null;
+        TestObject[] obj2 = new TestObject[3];
+        obj2[0] = new TestObject(4);
+        obj2[1] = new TestObject(5);
+        obj2[2] = null;
+
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj2, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1].setA(6);
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1].setA(5);
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[2] = obj1[1];
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[2] = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testLongArray() {
+        long[] obj1 = new long[2];
+        obj1[0] = 5L;
+        obj1[1] = 6L;
+        long[] obj2 = new long[2];
+        obj2[0] = 5L;
+        obj2[1] = 6L;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testIntArray() {
+        int[] obj1 = new int[2];
+        obj1[0] = 5;
+        obj1[1] = 6;
+        int[] obj2 = new int[2];
+        obj2[0] = 5;
+        obj2[1] = 6;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testShortArray() {
+        short[] obj1 = new short[2];
+        obj1[0] = 5;
+        obj1[1] = 6;
+        short[] obj2 = new short[2];
+        obj2[0] = 5;
+        obj2[1] = 6;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testCharArray() {
+        char[] obj1 = new char[2];
+        obj1[0] = 5;
+        obj1[1] = 6;
+        char[] obj2 = new char[2];
+        obj2[0] = 5;
+        obj2[1] = 6;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testByteArray() {
+        byte[] obj1 = new byte[2];
+        obj1[0] = 5;
+        obj1[1] = 6;
+        byte[] obj2 = new byte[2];
+        obj2[0] = 5;
+        obj2[1] = 6;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testDoubleArray() {
+        double[] obj1 = new double[2];
+        obj1[0] = 5;
+        obj1[1] = 6;
+        double[] obj2 = new double[2];
+        obj2[0] = 5;
+        obj2[1] = 6;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testFloatArray() {
+        float[] obj1 = new float[2];
+        obj1[0] = 5;
+        obj1[1] = 6;
+        float[] obj2 = new float[2];
+        obj2[0] = 5;
+        obj2[1] = 6;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testBooleanArray() {
+        boolean[] obj1 = new boolean[2];
+        obj1[0] = true;
+        obj1[1] = false;
+        boolean[] obj2 = new boolean[2];
+        obj2[0] = true;
+        obj2[1] = false;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1[1] = true;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+        obj2 = null;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+        obj1 = null;
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testMultiLongArray() {
+        long[][] array1 = new long[2][2];
+        long[][] array2 = new long[2][2];
+        for (int i = 0; i < array1.length; ++i) {
+            for (int j = 0; j < array1[0].length; j++) {
+                array1[i][j] = (i + 1) * (j + 1);
+                array2[i][j] = (i + 1) * (j + 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMultiIntArray() {
+        int[][] array1 = new int[2][2];
+        int[][] array2 = new int[2][2];
+        for (int i = 0; i < array1.length; ++i) {
+            for (int j = 0; j < array1[0].length; j++) {
+                array1[i][j] = (i + 1) * (j + 1);
+                array2[i][j] = (i + 1) * (j + 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMultiShortArray() {
+        short[][] array1 = new short[2][2];
+        short[][] array2 = new short[2][2];
+        for (short i = 0; i < array1.length; ++i) {
+            for (short j = 0; j < array1[0].length; j++) {
+                array1[i][j] = i;
+                array2[i][j] = i;
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMultiCharArray() {
+        char[][] array1 = new char[2][2];
+        char[][] array2 = new char[2][2];
+        for (char i = 0; i < array1.length; ++i) {
+            for (char j = 0; j < array1[0].length; j++) {
+                array1[i][j] = i;
+                array2[i][j] = i;
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMultiByteArray() {
+        byte[][] array1 = new byte[2][2];
+        byte[][] array2 = new byte[2][2];
+        for (byte i = 0; i < array1.length; ++i) {
+            for (byte j = 0; j < array1[0].length; j++) {
+                array1[i][j] = i;
+                array2[i][j] = i;
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+    @Test public void testMultiFloatArray() {
+        float[][] array1 = new float[2][2];
+        float[][] array2 = new float[2][2];
+        for (int i = 0; i < array1.length; ++i) {
+            for (int j = 0; j < array1[0].length; j++) {
+                array1[i][j] = (i + 1) * (j + 1);
+                array2[i][j] = (i + 1) * (j + 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMultiDoubleArray() {
+        double[][] array1 = new double[2][2];
+        double[][] array2 = new double[2][2];
+        for (int i = 0; i < array1.length; ++i) {
+            for (int j = 0; j < array1[0].length; j++) {
+                array1[i][j] = (i + 1) * (j + 1);
+                array2[i][j] = (i + 1) * (j + 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMultiBooleanArray() {
+        boolean[][] array1 = new boolean[2][2];
+        boolean[][] array2 = new boolean[2][2];
+        for (int i = 0; i < array1.length; ++i) {
+            for (int j = 0; j < array1[0].length; j++) {
+                array1[i][j] = (i == 1) || (j == 1);
+                array2[i][j] = (i == 1) || (j == 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = false;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+
+        // compare 1 dim to 2.
+        boolean[] array3 = new boolean[]{true, true};
+        assertFalse(new EqualsBuilder().append(array1, array3).isEquals());
+        assertFalse(new EqualsBuilder().append(array3, array1).isEquals());
+        assertFalse(new EqualsBuilder().append(array2, array3).isEquals());
+        assertFalse(new EqualsBuilder().append(array3, array2).isEquals());
+    }
+
+    @Test public void testRaggedArray() {
+        long[][] array1 = new long[2][];
+        long[][] array2 = new long[2][];
+        for (int i = 0; i < array1.length; ++i) {
+            array1[i] = new long[2];
+            array2[i] = new long[2];
+            for (int j = 0; j < array1[i].length; ++j) {
+                array1[i][j] = (i + 1) * (j + 1);
+                array2[i][j] = (i + 1) * (j + 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        array1[1][1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testMixedArray() {
+        Object[] array1 = new Object[2];
+        Object[] array2 = new Object[2];
+        for (int i = 0; i < array1.length; ++i) {
+            array1[i] = new long[2];
+            array2[i] = new long[2];
+            for (int j = 0; j < 2; ++j) {
+                ((long[]) array1[i])[j] = (i + 1) * (j + 1);
+                ((long[]) array2[i])[j] = (i + 1) * (j + 1);
+            }
+        }
+        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+        ((long[]) array1[1])[1] = 0;
+        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+    }
+
+    @Test public void testObjectArrayHiddenByObject() {
+        TestObject[] array1 = new TestObject[2];
+        array1[0] = new TestObject(4);
+        array1[1] = new TestObject(5);
+        TestObject[] array2 = new TestObject[2];
+        array2[0] = new TestObject(4);
+        array2[1] = new TestObject(5);
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1].setA(6);
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testLongArrayHiddenByObject() {
+        long[] array1 = new long[2];
+        array1[0] = 5L;
+        array1[1] = 6L;
+        long[] array2 = new long[2];
+        array2[0] = 5L;
+        array2[1] = 6L;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testIntArrayHiddenByObject() {
+        int[] array1 = new int[2];
+        array1[0] = 5;
+        array1[1] = 6;
+        int[] array2 = new int[2];
+        array2[0] = 5;
+        array2[1] = 6;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testShortArrayHiddenByObject() {
+        short[] array1 = new short[2];
+        array1[0] = 5;
+        array1[1] = 6;
+        short[] array2 = new short[2];
+        array2[0] = 5;
+        array2[1] = 6;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testCharArrayHiddenByObject() {
+        char[] array1 = new char[2];
+        array1[0] = 5;
+        array1[1] = 6;
+        char[] array2 = new char[2];
+        array2[0] = 5;
+        array2[1] = 6;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testByteArrayHiddenByObject() {
+        byte[] array1 = new byte[2];
+        array1[0] = 5;
+        array1[1] = 6;
+        byte[] array2 = new byte[2];
+        array2[0] = 5;
+        array2[1] = 6;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testDoubleArrayHiddenByObject() {
+        double[] array1 = new double[2];
+        array1[0] = 5;
+        array1[1] = 6;
+        double[] array2 = new double[2];
+        array2[0] = 5;
+        array2[1] = 6;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testFloatArrayHiddenByObject() {
+        float[] array1 = new float[2];
+        array1[0] = 5;
+        array1[1] = 6;
+        float[] array2 = new float[2];
+        array2[0] = 5;
+        array2[1] = 6;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = 7;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    @Test public void testBooleanArrayHiddenByObject() {
+        boolean[] array1 = new boolean[2];
+        array1[0] = true;
+        array1[1] = false;
+        boolean[] array2 = new boolean[2];
+        array2[0] = true;
+        array2[1] = false;
+        Object obj1 = array1;
+        Object obj2 = array2;
+        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+        array1[1] = true;
+        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+    }
+
+    public static class TestACanEqualB {
+        private int a;
+
+        public TestACanEqualB(int a) {
+            this.a = a;
+        }
+
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (o instanceof TestACanEqualB) {
+                return this.a == ((TestACanEqualB) o).getA();
+            }
+            if (o instanceof TestBCanEqualA) {
+                return this.a == ((TestBCanEqualA) o).getB();
+            }
+            return false;
+        }
+        public int hashCode() {
+            return 1;
+        }
+
+        public int getA() {
+            return this.a;
+        }
+    }
+
+    public static class TestBCanEqualA {
+        private int b;
+
+        public TestBCanEqualA(int b) {
+            this.b = b;
+        }
+
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (o instanceof TestACanEqualB) {
+                return this.b == ((TestACanEqualB) o).getA();
+            }
+            if (o instanceof TestBCanEqualA) {
+                return this.b == ((TestBCanEqualA) o).getB();
+            }
+            return false;
+        }
+        public int hashCode() {
+            return 1;
+        }
+
+        public int getB() {
+            return this.b;
+        }
+    }
+
+    /**
+     * Tests two instances of classes that can be equal and that are not "related". The two classes are not subclasses
+     * of each other and do not share a parent aside from Object.
+     * See http://issues.apache.org/bugzilla/show_bug.cgi?id=33069
+     */
+    @Test public void testUnrelatedClasses() {
+        Object[] x = new Object[]{new TestACanEqualB(1)};
+        Object[] y = new Object[]{new TestBCanEqualA(1)};
+
+        // sanity checks:
+        assertTrue(Arrays.equals(x, x));
+        assertTrue(Arrays.equals(y, y));
+        assertTrue(Arrays.equals(x, y));
+        assertTrue(Arrays.equals(y, x));
+        // real tests:
+        assertTrue(x[0].equals(x[0]));
+        assertTrue(y[0].equals(y[0]));
+        assertTrue(x[0].equals(y[0]));
+        assertTrue(y[0].equals(x[0]));
+        assertTrue(new EqualsBuilder().append(x, x).isEquals());
+        assertTrue(new EqualsBuilder().append(y, y).isEquals());
+        assertTrue(new EqualsBuilder().append(x, y).isEquals());
+        assertTrue(new EqualsBuilder().append(y, x).isEquals());
+    }
+
+    /**
+     * Test from http://issues.apache.org/bugzilla/show_bug.cgi?id=33067
+     */
+    @Test public void testNpeForNullElement() {
+        Object[] x1 = new Object[] { new Integer(1), null, new Integer(3) };
+        Object[] x2 = new Object[] { new Integer(1), new Integer(2), new Integer(3) };
+
+        // causes an NPE in 2.0 according to:
+        // http://issues.apache.org/bugzilla/show_bug.cgi?id=33067
+        new EqualsBuilder().append(x1, x2);
+    }
+
+    @Test public void testReflectionEqualsExcludeFields() throws Exception {
+        TestObjectWithMultipleFields x1 = new TestObjectWithMultipleFields(1, 2, 3);
+        TestObjectWithMultipleFields x2 = new TestObjectWithMultipleFields(1, 3, 4);
+
+        // not equal when including all fields
+        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2));
+
+        // doesn't barf on null, empty array, or non-existent field, but still tests as not equal
+        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, (String[]) null));
+        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {}));
+        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {"xxx"}));
+
+        // not equal if only one of the differing fields excluded
+        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {"two"}));
+        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {"three"}));
+
+        // equal if both differing fields excluded
+        assertTrue(EqualsBuilder.reflectionEquals(x1, x2, new String[] {"two", "three"}));
+
+        // still equal as long as both differing fields are among excluded
+        assertTrue(EqualsBuilder.reflectionEquals(x1, x2, new String[] {"one", "two", "three"}));
+        assertTrue(EqualsBuilder.reflectionEquals(x1, x2, new String[] {"one", "two", "three", "xxx"}));
+    }
+
+    @SuppressWarnings("unused")
+    static class TestObjectWithMultipleFields {
+        private TestObject one;
+        private TestObject two;
+        private TestObject three;
+
+        public TestObjectWithMultipleFields(int one, int two, int three) {
+            this.one = new TestObject(one);
+            this.two = new TestObject(two);
+            this.three = new TestObject(three);
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/text/MatcherToStringTest.java b/src/test/java/org/mockito/internal/matchers/text/MatcherToStringTest.java
new file mode 100644
index 0000000..3631447
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/text/MatcherToStringTest.java
@@ -0,0 +1,38 @@
+package org.mockito.internal.matchers.text;
+
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class MatcherToStringTest extends TestBase {
+
+    static class MatcherWithoutDescription implements ArgumentMatcher<Object> {
+        public boolean matches(Object argument) {
+            return false;
+        }
+    }
+
+    static class MatcherWithDescription implements ArgumentMatcher<Object> {
+        public boolean matches(Object argument) {
+            return false;
+        }
+        public String toString() {
+            return "*my custom description*";
+        }
+    }
+
+    static class MatcherWithInheritedDescription extends MatcherWithDescription {
+        public boolean matches(Object argument) {
+            return false;
+        }
+    }
+
+    @Test
+    public void better_toString_for_matchers() {
+        assertEquals("<Matcher without description>", MatcherToString.toString(new MatcherWithoutDescription()));
+        assertEquals("*my custom description*", MatcherToString.toString(new MatcherWithDescription()));
+        assertEquals("*my custom description*", MatcherToString.toString(new MatcherWithInheritedDescription()));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/matchers/text/ValuePrinterTest.java b/src/test/java/org/mockito/internal/matchers/text/ValuePrinterTest.java
new file mode 100644
index 0000000..84d6fc9
--- /dev/null
+++ b/src/test/java/org/mockito/internal/matchers/text/ValuePrinterTest.java
@@ -0,0 +1,60 @@
+package org.mockito.internal.matchers.text;
+
+
+import java.util.LinkedHashMap;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.internal.matchers.text.ValuePrinter.print;
+
+public class ValuePrinterTest {
+
+    @Test
+    public void prints_values() {
+        assertThat(print(null)).isEqualTo("null");
+        assertThat(print("str")).isEqualTo("\"str\"");
+        assertThat(print("x\ny")).isEqualTo("\"x\ny\"");
+        assertThat(print(3)).isEqualTo("3");
+        assertThat(print(3L)).isEqualTo("3L");
+        assertThat(print(3.14d)).isEqualTo("3.14d");
+        assertThat(print(3.14f)).isEqualTo("3.14f");
+        assertThat(print(new int[]{1, 2})).isEqualTo("[1, 2]");
+        assertThat(print(new LinkedHashMap<String, Object>() {{
+            put("foo", 2L);
+        }})).isEqualTo("{\"foo\" = 2L}");
+        assertThat(print(new LinkedHashMap<String, Object>() {{
+            put("int passed as hex", 0x01);
+            put("byte", (byte) 0x01);
+            put("short", (short) 2);
+            put("int", 3);
+            put("long", 4L);
+            put("float", 2.71f);
+            put("double", 3.14d);
+        }})).isEqualTo("{\"int passed as hex\" = 1, \"byte\" = (byte) 0x01, \"short\" = (short) 2, \"int\" = 3, \"long\" = 4L, \"float\" = 2.71f, \"double\" = 3.14d}");
+        assertTrue(print(new UnsafeToString()).contains("UnsafeToString"));
+        assertThat(print(new ToString())).isEqualTo("ToString");
+        assertThat(print(new FormattedText("formatted"))).isEqualTo("formatted");
+    }
+
+    @Test
+    public void prints_chars() {
+        assertThat(print('a')).isEqualTo("'a'");
+        assertThat(print('\n')).isEqualTo("'\\n'");
+        assertThat(print('\t')).isEqualTo("'\\t'");
+        assertThat(print('\r')).isEqualTo("'\\r'");
+    }
+
+    static class ToString {
+        public String toString() {
+            return "ToString";
+        }
+
+    }
+    static class UnsafeToString {
+        public String toString() {
+            throw new RuntimeException("ka-boom!");
+        }
+
+    }
+}
diff --git a/src/test/java/org/mockito/internal/progress/AtLeastTest.java b/src/test/java/org/mockito/internal/progress/AtLeastTest.java
new file mode 100644
index 0000000..d6657d8
--- /dev/null
+++ b/src/test/java/org/mockito/internal/progress/AtLeastTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.progress;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class AtLeastTest extends TestBase {
+
+    @Test
+    public void shouldNotAllowNegativeNumberOfMinimumInvocations() throws Exception {
+        try {
+            VerificationModeFactory.atLeast(-50);
+            fail();
+        } catch (MockitoException e) {
+            assertEquals("Negative value is not allowed here", e.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldAllowZeroInvocations() throws Exception {
+        VerificationModeFactory.atLeast(0);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java b/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java
new file mode 100644
index 0000000..b604e94
--- /dev/null
+++ b/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.verification.VerificationMode;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class MockingProgressImplTest extends TestBase {
+
+    private MockingProgress mockingProgress;
+
+    @Before
+    public void setup() {
+        mockingProgress = new MockingProgressImpl();
+    }
+
+    @Test
+    public void shouldStartVerificationAndPullVerificationMode() throws Exception {
+        assertNull(mockingProgress.pullVerificationMode());
+
+        VerificationMode mode = VerificationModeFactory.times(19);
+
+        mockingProgress.verificationStarted(mode);
+
+        assertSame(mode, mockingProgress.pullVerificationMode());
+
+        assertNull(mockingProgress.pullVerificationMode());
+    }
+
+    @Test
+    public void shouldCheckIfVerificationWasFinished() throws Exception {
+        mockingProgress.verificationStarted(VerificationModeFactory.atLeastOnce());
+        try {
+            mockingProgress.verificationStarted(VerificationModeFactory.atLeastOnce());
+            fail();
+        } catch (MockitoException e) {}
+    }
+
+    @Test
+    public void shouldNotifyListenerSafely() throws Exception {
+        //when
+        mockingProgress.addListener(null);
+
+        //then no exception is thrown:
+        mockingProgress.mockingStarted(null, null);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/progress/ThreadSafeMockingProgressTest.java b/src/test/java/org/mockito/internal/progress/ThreadSafeMockingProgressTest.java
new file mode 100644
index 0000000..3a1c229
--- /dev/null
+++ b/src/test/java/org/mockito/internal/progress/ThreadSafeMockingProgressTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.progress;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.internal.verification.DummyVerificationMode;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
+public class ThreadSafeMockingProgressTest extends TestBase {
+
+    @After
+    public void after() {
+        this.resetState();
+    }
+
+    @Test
+    public void shouldShareState() throws Exception {
+        //given
+        MockingProgress p = mockingProgress();
+        p.verificationStarted(new DummyVerificationMode());
+
+        //then
+        p = mockingProgress();
+        assertNotNull(p.pullVerificationMode());
+    }
+
+    @Test
+    public void shouldKnowWhenVerificationHasStarted() throws Exception {
+        //given
+        verify(mock(List.class));
+        MockingProgress p = mockingProgress();
+
+        //then
+        assertNotNull(p.pullVerificationMode());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/progress/TimesTest.java b/src/test/java/org/mockito/internal/progress/TimesTest.java
new file mode 100644
index 0000000..d0095bd
--- /dev/null
+++ b/src/test/java/org/mockito/internal/progress/TimesTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.verification.VerificationModeFactory;
+
+
+public class TimesTest  {
+	@Rule
+	public ExpectedException exception = ExpectedException.none();
+
+    @Test
+    public void shouldNotAllowNegativeNumberOfInvocations() throws Exception {
+
+    	exception.expect(MockitoException.class);
+    	exception.expectMessage("Negative value is not allowed here");
+
+    	VerificationModeFactory.times(-50);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/progress/VerificationModeBuilder.java b/src/test/java/org/mockito/internal/progress/VerificationModeBuilder.java
new file mode 100644
index 0000000..a22fabd
--- /dev/null
+++ b/src/test/java/org/mockito/internal/progress/VerificationModeBuilder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+
+import org.mockito.internal.verification.Times;
+import org.mockito.internal.verification.VerificationModeFactory;
+
+public class VerificationModeBuilder {
+
+    private Integer times = 1;
+
+    public Times inOrder() {
+        return VerificationModeFactory.times(times);
+    }
+
+    public VerificationModeBuilder times(int times) {
+        this.times = times;
+        return this;
+    }
+}
diff --git a/src/test/java/org/mockito/internal/reporting/PluralizerTest.java b/src/test/java/org/mockito/internal/reporting/PluralizerTest.java
new file mode 100644
index 0000000..c2e1333
--- /dev/null
+++ b/src/test/java/org/mockito/internal/reporting/PluralizerTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.reporting;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class PluralizerTest extends TestBase {
+
+    @Test
+    public void pluralizes_number() {
+        assertEquals("0 times", Pluralizer.pluralize(0));
+        assertEquals("1 time", Pluralizer.pluralize(1));
+        assertEquals("2 times", Pluralizer.pluralize(2));
+        assertEquals("20 times", Pluralizer.pluralize(20));
+    }
+
+    @Test
+    public void pluralizes_interactions() {
+        assertEquals("were exactly 0 interactions", Pluralizer.were_exactly_x_interactions(0));
+        assertEquals("was exactly 1 interaction", Pluralizer.were_exactly_x_interactions(1));
+        assertEquals("were exactly 100 interactions", Pluralizer.were_exactly_x_interactions(100));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/runners/util/RunnerProviderTest.java b/src/test/java/org/mockito/internal/runners/util/RunnerProviderTest.java
new file mode 100644
index 0000000..c17a219
--- /dev/null
+++ b/src/test/java/org/mockito/internal/runners/util/RunnerProviderTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners.util;
+
+import org.junit.Test;
+import org.mockito.internal.runners.DefaultInternalRunner;
+import org.mockito.internal.runners.InternalRunner;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertNotNull;
+
+public class RunnerProviderTest extends TestBase {
+
+    @Test
+    public void shouldCreateRunnerInstance() throws Throwable {
+        //given
+        RunnerProvider provider = new RunnerProvider();
+        //when
+        InternalRunner runner = provider.newInstance(DefaultInternalRunner.class.getName(), this.getClass(), null);
+        //then
+        assertNotNull(runner);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/runners/util/TestMethodsFinderTest.java b/src/test/java/org/mockito/internal/runners/util/TestMethodsFinderTest.java
new file mode 100644
index 0000000..e6297cf
--- /dev/null
+++ b/src/test/java/org/mockito/internal/runners/util/TestMethodsFinderTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners.util;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+public class TestMethodsFinderTest extends TestBase {
+
+    public static class HasTests {
+        @Test public void someTest() {}
+    }
+
+    static class DoesNotHaveTests {
+        public void someTest() {}
+    }
+
+    @Test
+    public void shouldKnowWhenClassHasTests() {
+        assertTrue(TestMethodsFinder.hasTestMethods(HasTests.class));
+        assertFalse(TestMethodsFinder.hasTestMethods(DoesNotHaveTests.class));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java b/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java
new file mode 100644
index 0000000..8c0a5ae
--- /dev/null
+++ b/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java
@@ -0,0 +1,40 @@
+package org.mockito.internal.session;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.StateMaster;
+import org.mockito.exceptions.misusing.UnfinishedMockingSessionException;
+import org.mockito.quality.Strictness;
+import org.mockitoutil.ThrowableAssert;
+
+public class DefaultMockitoSessionBuilderTest {
+
+    @After public void after() {
+        new StateMaster().clearMockitoListeners();
+    }
+
+    @Test public void creates_sessions() throws Exception {
+        //no configuration is legal
+        new DefaultMockitoSessionBuilder().startMocking().finishMocking();
+
+        //passing null to configuration is legal, default value will be used
+        new DefaultMockitoSessionBuilder().initMocks(null).startMocking().finishMocking();
+        new DefaultMockitoSessionBuilder().initMocks(null).strictness(null).startMocking().finishMocking();
+        new DefaultMockitoSessionBuilder().strictness(null).startMocking().finishMocking();
+
+        //happy path
+        new DefaultMockitoSessionBuilder().initMocks(this).startMocking().finishMocking();
+        new DefaultMockitoSessionBuilder().initMocks(new Object()).startMocking().finishMocking();
+        new DefaultMockitoSessionBuilder().strictness(Strictness.LENIENT).startMocking().finishMocking();
+    }
+
+    @Test public void requires_finish_mocking() throws Exception {
+        new DefaultMockitoSessionBuilder().startMocking();
+
+        ThrowableAssert.assertThat(new Runnable() {
+            public void run() {
+                new DefaultMockitoSessionBuilder().startMocking();
+            }
+        }).throwsException(UnfinishedMockingSessionException.class);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/InvocationContainerImplStubbingTest.java b/src/test/java/org/mockito/internal/stubbing/InvocationContainerImplStubbingTest.java
new file mode 100644
index 0000000..96e8720
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/InvocationContainerImplStubbingTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.stubbing;
+
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.invocation.Invocation;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class InvocationContainerImplStubbingTest extends TestBase {
+
+    private InvocationContainerImpl invocationContainerImpl;
+    private InvocationContainerImpl invocationContainerImplStubOnly;
+    private MockingProgress state;
+    private Invocation simpleMethod;
+
+    @Before
+    public void setup() {
+        state = mockingProgress();
+
+        invocationContainerImpl = new InvocationContainerImpl(new MockSettingsImpl());
+        invocationContainerImpl.setInvocationForPotentialStubbing(new InvocationBuilder().toInvocationMatcher());
+
+        invocationContainerImplStubOnly =
+          new InvocationContainerImpl( new MockSettingsImpl().stubOnly());
+        invocationContainerImplStubOnly.setInvocationForPotentialStubbing(new InvocationBuilder().toInvocationMatcher());
+
+        simpleMethod = new InvocationBuilder().simpleMethod().toInvocation();
+    }
+
+    @Test
+    public void should_finish_stubbing_when_wrong_throwable_is_set() throws Exception {
+        state.stubbingStarted();
+        try {
+            invocationContainerImpl.addAnswer(new ThrowsException(new Exception()));
+            fail();
+        } catch (MockitoException e) {
+            state.validateState();
+        }
+    }
+
+    @Test
+    public void should_finish_stubbing_on_adding_return_value() throws Exception {
+        state.stubbingStarted();
+        invocationContainerImpl.addAnswer(new Returns("test"));
+        state.validateState();
+    }
+
+    @Test
+    public void should_get_results_for_methods() throws Throwable {
+        invocationContainerImpl.setInvocationForPotentialStubbing(new InvocationMatcher(simpleMethod));
+        invocationContainerImpl.addAnswer(new Returns("simpleMethod"));
+
+        Invocation differentMethod = new InvocationBuilder().differentMethod().toInvocation();
+        invocationContainerImpl.setInvocationForPotentialStubbing(new InvocationMatcher(differentMethod));
+        invocationContainerImpl.addAnswer(new ThrowsException(new MyException()));
+
+        assertEquals("simpleMethod", invocationContainerImpl.answerTo(simpleMethod));
+
+        try {
+            invocationContainerImpl.answerTo(differentMethod);
+            fail();
+        } catch (MyException e) {}
+    }
+
+    @Test
+    public void should_get_results_for_methods_stub_only() throws Throwable {
+        invocationContainerImplStubOnly.setInvocationForPotentialStubbing(new InvocationMatcher(simpleMethod));
+        invocationContainerImplStubOnly.addAnswer(new Returns("simpleMethod"));
+
+        Invocation differentMethod = new InvocationBuilder().differentMethod().toInvocation();
+        invocationContainerImplStubOnly.setInvocationForPotentialStubbing(new InvocationMatcher(differentMethod));
+        invocationContainerImplStubOnly.addAnswer(new ThrowsException(new MyException()));
+
+        assertEquals("simpleMethod", invocationContainerImplStubOnly.answerTo(simpleMethod));
+
+        try {
+            invocationContainerImplStubOnly.answerTo(differentMethod);
+            fail();
+        } catch (MyException e) {}
+    }
+
+    @Test
+    public void should_add_throwable_for_void_method() throws Throwable {
+        invocationContainerImpl.addAnswerForVoidMethod(new ThrowsException(new MyException()));
+        invocationContainerImpl.setMethodForStubbing(new InvocationMatcher(simpleMethod));
+
+        try {
+            invocationContainerImpl.answerTo(simpleMethod);
+            fail();
+        } catch (MyException e) {}
+    }
+
+    @Test
+    public void should_validate_throwable_for_void_method() throws Throwable {
+        invocationContainerImpl.addAnswerForVoidMethod(new ThrowsException(new Exception()));
+
+        try {
+            invocationContainerImpl.setMethodForStubbing(new InvocationMatcher(simpleMethod));
+            fail();
+        } catch (MockitoException e) {}
+    }
+
+    @Test
+    public void should_validate_throwable() throws Throwable {
+        try {
+            invocationContainerImpl.addAnswer(new ThrowsException(null));
+            fail();
+        } catch (MockitoException e) {}
+    }
+
+    @SuppressWarnings("serial")
+    class MyException extends RuntimeException {}
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/InvocationContainerImplTest.java b/src/test/java/org/mockito/internal/stubbing/InvocationContainerImplTest.java
new file mode 100644
index 0000000..176372f
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/InvocationContainerImplTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.LinkedList;
+import java.util.concurrent.CountDownLatch;
+import org.junit.Test;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+
+/**
+ * Author: Szczepan Faber
+ */
+public class InvocationContainerImplTest {
+
+    InvocationContainerImpl container = new InvocationContainerImpl( new MockSettingsImpl());
+    InvocationContainerImpl containerStubOnly =
+      new InvocationContainerImpl( (MockCreationSettings) new MockSettingsImpl().stubOnly());
+    Invocation invocation = new InvocationBuilder().toInvocation();
+    LinkedList<Throwable> exceptions = new LinkedList<Throwable>();
+
+    @Test
+    public void should_be_thread_safe() throws Throwable {
+        doShouldBeThreadSafe(container);
+    }
+
+    @Test
+    public void should_be_thread_safe_stub_only() throws Throwable {
+        doShouldBeThreadSafe(containerStubOnly);
+    }
+
+    //works 50% of the time
+    private void doShouldBeThreadSafe(final InvocationContainerImpl c) throws Throwable {
+        //given
+        Thread[] t = new Thread[200];
+        final CountDownLatch starter = new CountDownLatch(200);
+        for (int i = 0; i < t.length; i++ ) {
+            t[i] = new Thread() {
+                public void run() {
+                    try {
+                        starter.await(); //NOPMD
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
+                    c.setInvocationForPotentialStubbing(new InvocationMatcher(invocation));
+                    c.addAnswer(new Returns("foo"));
+                    c.findAnswerFor(invocation);
+                }
+            };
+            t[i].setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                public void uncaughtException(Thread t, Throwable e) {
+                    exceptions.add(e);
+                }
+            });
+            t[i].start();
+
+            starter.countDown();
+        }
+
+        //when
+        for (Thread aT : t) {
+            aT.join();
+        }
+
+        //then
+        if (exceptions.size() != 0) {
+            throw exceptions.getFirst();
+        }
+    }
+
+    @Test
+    public void should_return_invoked_mock() throws Exception {
+        container.setInvocationForPotentialStubbing(new InvocationMatcher(invocation));
+
+        assertEquals(invocation.getMock(), container.invokedMock());
+    }
+
+    @Test
+    public void should_return_invoked_mock_stub_only() throws Exception {
+        containerStubOnly.setInvocationForPotentialStubbing(new InvocationMatcher(invocation));
+
+        assertEquals(invocation.getMock(), containerStubOnly.invokedMock());
+    }
+
+    @Test
+    public void should_tell_if_has_invocation_for_potential_stubbing() throws Exception {
+        container.setInvocationForPotentialStubbing(new InvocationBuilder().toInvocationMatcher());
+        assertTrue(container.hasInvocationForPotentialStubbing());
+
+        container.addAnswer(new ReturnsEmptyValues());
+        assertFalse(container.hasInvocationForPotentialStubbing());
+    }
+
+    @Test
+    public void should_tell_if_has_invocation_for_potential_stubbing_stub_only() throws Exception {
+        containerStubOnly.setInvocationForPotentialStubbing(new InvocationBuilder().toInvocationMatcher());
+        assertTrue(containerStubOnly.hasInvocationForPotentialStubbing());
+
+        containerStubOnly.addAnswer(new ReturnsEmptyValues());
+        assertFalse(containerStubOnly.hasInvocationForPotentialStubbing());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/CallsRealMethodsTest.java b/src/test/java/org/mockito/internal/stubbing/answers/CallsRealMethodsTest.java
new file mode 100644
index 0000000..28b2426
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/CallsRealMethodsTest.java
@@ -0,0 +1,67 @@
+
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.util.ArrayList;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEFAULTS;
+import static org.mockito.Mockito.mock;
+
+public class CallsRealMethodsTest {
+    @Test
+    public void should_invoke_real_method() throws Throwable {
+        class Concrete {
+            void concrete() {
+                throw new RuntimeException("real code");
+            }
+        }
+        Concrete mock = mock(Concrete.class);
+
+        Invocation concrete = new InvocationBuilder().mock(mock).method(Concrete.class.getDeclaredMethod("concrete")).toInvocation();
+        try {
+            new CallsRealMethods().answer(concrete);
+        } catch (RuntimeException throwable) {
+            throwable.printStackTrace();
+            assertThat(throwable).hasMessage("real code");
+        }
+    }
+
+    @Test
+    public void should_delegate_to_returns_default_when_abstract_method() throws Throwable {
+        Invocation abstractMethod = new InvocationBuilder().method("booleanReturningMethod").toInvocation();
+        assertThat(new CallsRealMethods().answer(abstractMethod)).isEqualTo(RETURNS_DEFAULTS.answer(abstractMethod));
+    }
+
+    @Test
+    public void should_fail_when_calling_real_method_on_interface() throws Throwable {
+        //given
+        Invocation invocationOnInterface = new InvocationBuilder().method("simpleMethod").toInvocation();
+        try {
+            //when
+            new CallsRealMethods().validateFor(invocationOnInterface);
+            //then
+            Assertions.fail("can not invoke interface");
+        } catch (MockitoException expected) {}
+    }
+
+    @Test
+    public void should_be_OK_when_calling_real_method_on_concrete_class() throws Throwable {
+        //given
+        ArrayList<?> mock = mock(ArrayList.class);
+        mock.clear();
+        Invocation invocationOnClass = new MockitoCore().getLastInvocation();
+        //when
+        new CallsRealMethods().validateFor(invocationOnClass);
+        //then no exception is thrown
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidatorTest.java b/src/test/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidatorTest.java
new file mode 100644
index 0000000..9caed65
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidatorTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.junit.Test;
+import org.mockito.exceptions.misusing.WrongTypeOfReturnValue;
+import org.mockito.internal.invocation.InvocationBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+public class DefaultAnswerValidatorTest {
+
+    @Test
+    public void should_fail_if_returned_value_of_answer_is_incompatible_with_return_type() throws Throwable {
+        // given
+        class AWrongType {
+        }
+        try {
+            // when
+            DefaultAnswerValidator.validateReturnValueFor(new InvocationBuilder().method("toString").toInvocation(),
+                                                          new AWrongType());
+            fail("expected validation to fail");
+        } catch (WrongTypeOfReturnValue e) {
+            // then
+            assertThat(e.getMessage())
+                    .containsIgnoringCase("Default answer returned a result with the wrong type")
+                    .containsIgnoringCase("AWrongType cannot be returned by toString()")
+                    .containsIgnoringCase("toString() should return String");
+        }
+    }
+
+    @Test
+    public void should_not_fail_if_returned_value_of_answer_is_null() throws Throwable {
+        DefaultAnswerValidator.validateReturnValueFor(new InvocationBuilder().method("toString").toInvocation(),
+                                                      null);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java b/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java
new file mode 100644
index 0000000..f3c83ff
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.internal.stubbing.answers.DoesNothing.doesNothing;
+import static org.mockitoutil.TestBase.getLastInvocation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+
+public class DoesNothingTest   {
+
+    private IMethods mock;
+    private Invocation invocation_Void;
+    private Invocation invocation_void;
+    private Invocation invocation_String;
+
+    @Before
+    public void init(){
+        mock = mock(IMethods.class);
+
+        mock.voidMethod();
+        invocation_Void = getLastInvocation();
+
+        mock.voidReturningMethod();
+        invocation_void = getLastInvocation();
+
+        mock.simpleMethod();
+        invocation_String = getLastInvocation();
+    }
+
+    @Test
+    public void answer_returnsNull() throws Throwable {
+        assertThat(doesNothing().answer(invocation_Void)).isNull();
+        assertThat(doesNothing().answer(invocation_void)).isNull();
+        assertThat(doesNothing().answer(invocation_String)).isNull();
+    }
+
+    @Test(expected = MockitoException.class)
+    public void validateFor_nonVoidReturnType_shouldFail()   {
+        doesNothing().validateFor(invocation_String);
+    }
+
+    @Test
+    public void validateFor_voidReturnType_shouldPass()   {
+        doesNothing().validateFor(invocation_void);
+    }
+
+    @Test
+    public void validateFor_voidObjectReturnType() throws Throwable {
+        doesNothing().validateFor(invocation_Void);
+    }
+
+
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java b/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java
new file mode 100644
index 0000000..d683605
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.lang.reflect.Method;
+import java.nio.charset.CharacterCodingException;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockitoutil.TestBase.getLastInvocation;
+
+public class InvocationInfoTest {
+
+    @Test
+    public void should_know_valid_throwables() throws Exception {
+        //when
+        Invocation invocation = new InvocationBuilder().method("canThrowException").toInvocation();
+        InvocationInfo info = new InvocationInfo(invocation);
+
+        //then
+        assertThat(info.isValidException(new Exception())).isFalse();
+        assertThat(info.isValidException(new CharacterCodingException())).isTrue();
+    }
+
+    @Test
+    public void should_know_valid_return_types() throws Exception {
+        assertThat(new InvocationInfo(new InvocationBuilder().method("integerReturningMethod").toInvocation()).isValidReturnType(Integer.class)).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("integerReturningMethod").toInvocation()).isValidReturnType(int.class)).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("intReturningMethod").toInvocation()).isValidReturnType(Integer.class)).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("intReturningMethod").toInvocation()).isValidReturnType(int.class)).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("integerReturningMethod").toInvocation()).isValidReturnType(String.class)).isFalse();
+    }
+
+    @Test
+    public void should_know_when_invocation_returns_primitive() {
+        assertThat(new InvocationInfo(new InvocationBuilder().method("intReturningMethod").toInvocation()).returnsPrimitive()).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("integerReturningMethod").toInvocation()).returnsPrimitive()).isFalse();
+    }
+
+    @Test
+    public void should_know_when_invocation_returns_void() {
+        assertThat(new InvocationInfo(new InvocationBuilder().method("voidMethod").toInvocation()).isVoid()).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("integerReturningMethod").toInvocation()).isVoid()).isFalse();
+    }
+
+    @Test
+    public void should_read_the_method_name() {
+        assertThat(new InvocationInfo(new InvocationBuilder().method("voidMethod").toInvocation()).getMethodName()).isEqualTo("voidMethod");
+    }
+
+    @Test
+    public void should_read_the_method_return_name() {
+        assertThat(new InvocationInfo(new InvocationBuilder().method("voidMethod").toInvocation()).printMethodReturnType()).isEqualTo("void");
+        assertThat(new InvocationInfo(new InvocationBuilder().method("integerReturningMethod").toInvocation()).printMethodReturnType()).isEqualTo("Integer");
+        assertThat(new InvocationInfo(new InvocationBuilder().method("intReturningMethod").toInvocation()).printMethodReturnType()).isEqualTo("int");
+    }
+
+    @Test
+    public void should_know_abstract_method() throws Exception { // To be extended with Java 8
+        assertThat(new InvocationInfo(new InvocationBuilder().method(iAmAbstract()).toInvocation()).isAbstract()).isTrue();
+        assertThat(new InvocationInfo(new InvocationBuilder().method(iAmNotAbstract()).toInvocation()).isAbstract()).isFalse();
+    }
+
+    @Test
+    public void should_know_method_is_declared_on_interface() throws Exception {
+        assertThat(new InvocationInfo(new InvocationBuilder().method(iAmAbstract()).toInvocation()).isDeclaredOnInterface()).isFalse();
+        assertThat(new InvocationInfo(new InvocationBuilder().method("voidMethod").toInvocation()).isDeclaredOnInterface()).isTrue();
+    }
+
+    @Test
+    public void isVoid_invocationOnVoidMethod_returnTrue(){
+        mock(IMethods.class).voidMethod();
+
+        InvocationInfo voidMethod = new InvocationInfo(getLastInvocation());
+
+        assertThat(voidMethod.isVoid()).isTrue();
+    }
+
+    @Test
+    public void isVoid_invocationOnVoidReturningMethod_returnTrue(){
+        mock(IMethods.class).voidReturningMethod();
+
+        InvocationInfo voidRetuningMethod = new InvocationInfo(getLastInvocation());
+
+        assertThat(voidRetuningMethod.isVoid()).isTrue();
+    }
+
+    @Test
+    public void isVoid_invocationNonVoidMethod_returnFalse(){
+        mock(IMethods.class).simpleMethod();
+
+        InvocationInfo stringReturningMethod = new InvocationInfo(getLastInvocation());
+
+        assertThat(stringReturningMethod.isVoid()).isFalse();
+    }
+
+    private Method iAmAbstract() throws NoSuchMethodException {
+        abstract class TheAbstract {
+            abstract void iAmAbstract();
+        }
+        return TheAbstract.class.getDeclaredMethod("iAmAbstract");
+    }
+
+    private Method iAmNotAbstract() throws NoSuchMethodException {
+        abstract class TheNotAbstract {
+            void iAmNotAbstract() {};
+        }
+        return TheNotAbstract.class.getDeclaredMethod("iAmNotAbstract");
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java b/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java
new file mode 100644
index 0000000..f72005a
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.WrongTypeOfReturnValue;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.InvocationOnMock;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+public class ReturnsArgumentAtTest {
+    @Test
+    public void should_be_able_to_return_the_first_parameter() throws Throwable {
+        assertThat(new ReturnsArgumentAt(0).answer(invocationWith("A", "B"))).isEqualTo("A");
+    }
+
+    @Test
+    public void should_be_able_to_return_the_second_parameter()
+            throws Throwable {
+        assertThat(new ReturnsArgumentAt(1).answer(invocationWith("A", "B", "C"))).isEqualTo("B");
+    }
+
+    @Test
+    public void should_be_able_to_return_the_last_parameter() throws Throwable {
+        assertThat(new ReturnsArgumentAt(-1).answer(invocationWith("A"))).isEqualTo("A");
+        assertThat(new ReturnsArgumentAt(-1).answer(invocationWith("A", "B"))).isEqualTo("B");
+    }
+
+    @Test
+    public void should_be_able_to_return_the_specified_parameter() throws Throwable {
+        assertThat(new ReturnsArgumentAt(0).answer(invocationWith("A", "B", "C"))).isEqualTo("A");
+        assertThat(new ReturnsArgumentAt(1).answer(invocationWith("A", "B", "C"))).isEqualTo("B");
+        assertThat(new ReturnsArgumentAt(2).answer(invocationWith("A", "B", "C"))).isEqualTo("C");
+    }
+
+    @Test
+    public void should_identify_bad_parameter_type_for_invocation() throws Exception {
+        try {
+            new ReturnsArgumentAt(1).validateFor(new InvocationBuilder().method("varargsReturningString")
+                                                                        .argTypes(Object[].class)
+                                                                        .args(new Object(), new Object(), new Object())
+                                                                        .toInvocation());
+            Assertions.fail("should scream");
+        } catch (WrongTypeOfReturnValue ignored) { }
+        try {
+            new ReturnsArgumentAt(0).validateFor(new InvocationBuilder().method("oneArray")
+                                                                        .argTypes(boolean[].class)
+                                                                        .args(true, false, false)
+                                                                        .toInvocation());
+            Assertions.fail("should scream");
+        } catch (WrongTypeOfReturnValue ignored) { }
+        try {
+            new ReturnsArgumentAt(0).validateFor(new InvocationBuilder().method("mixedVarargsReturningString")
+                                                                        .argTypes(Object.class, String[].class)
+                                                                        .args(new Object(), new String[]{"A", "B", "C"})
+                                                                        .toInvocation());
+            Assertions.fail("should scream");
+        } catch (WrongTypeOfReturnValue ignored) { }
+    }
+
+    @Test
+    public void should_not_scream_when_mixed_vararg_parameter_is_compatible_with_invocation() throws Exception {
+        new ReturnsArgumentAt(1).validateFor(new InvocationBuilder().method("mixedVarargsReturningString")
+                                                                    .argTypes(Object.class, String[].class)
+                                                                    .args(new Object(), new String[]{"A", "B", "C"})
+                                                                    .toInvocation());
+    }
+
+        @Test
+    public void should_handle_returning_vararg_as_array() throws Throwable {
+        Invocation mixedVarargsReturningStringArray = new InvocationBuilder().method("mixedVarargsReturningStringArray")
+                                                                             .argTypes(Object.class, String[].class)
+                                                                             .args(new Object(), new String[]{"A", "B", "C"})
+                                                                             .toInvocation();
+        new ReturnsArgumentAt(1).validateFor(mixedVarargsReturningStringArray);
+        assertThat(new ReturnsArgumentAt(1).answer(mixedVarargsReturningStringArray)).isEqualTo(new String[]{"A", "B", "C"});
+
+        Invocation mixedVarargsReturningObjectArray = new InvocationBuilder().method("mixedVarargsReturningStringArray")
+                                                                             .argTypes(Object.class, String[].class)
+                                                                             .args(new Object(), new String[]{"A", "B", "C"})
+                                                                             .toInvocation();
+        new ReturnsArgumentAt(1).validateFor(mixedVarargsReturningObjectArray);
+        assertThat(new ReturnsArgumentAt(1).answer(mixedVarargsReturningObjectArray)).isEqualTo(new String[]{"A", "B", "C"});
+    }
+
+    @Test
+    public void should_raise_an_exception_if_index_is_not_in_allowed_range_at_creation_time() throws Throwable {
+        try {
+            new ReturnsArgumentAt(-30);
+            fail();
+        } catch (Exception e) {
+            assertThat(e.getMessage()).containsIgnoringCase("argument index")
+                                      .containsIgnoringCase("positive number")
+                                      .contains("1")
+                                      .containsIgnoringCase("last argument");
+        }
+    }
+
+    @Test
+    public void should_allow_possible_argument_types() throws Exception {
+        new ReturnsArgumentAt(0).validateFor(
+                new InvocationBuilder().method("intArgumentReturningInt")
+                                       .argTypes(int.class)
+                                       .arg(1000)
+                                       .toInvocation()
+        );
+        new ReturnsArgumentAt(0).validateFor(
+                new InvocationBuilder().method("toString")
+                                       .argTypes(String.class)
+                                       .arg("whatever")
+                                       .toInvocation()
+        );
+        new ReturnsArgumentAt(2).validateFor(
+                new InvocationBuilder().method("varargsObject")
+                                       .argTypes(int.class, Object[].class)
+                                       .args(1000, "Object", "Object")
+                                       .toInvocation()
+        );
+        new ReturnsArgumentAt(1).validateFor(
+                new InvocationBuilder().method("threeArgumentMethod")
+                                       .argTypes(int.class, Object.class, String.class)
+                                       .args(1000, "Object", "String")
+                                       .toInvocation()
+        );
+    }
+
+    @Test
+    public void should_fail_if_index_is_not_in_range_for_one_arg_invocation() throws Throwable {
+        try {
+            new ReturnsArgumentAt(30).validateFor(new InvocationBuilder().method("oneArg")
+                                                                         .arg("A")
+                                                                         .toInvocation());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage())
+                    .containsIgnoringCase("invalid argument index")
+                    .containsIgnoringCase("iMethods.oneArg")
+                    .containsIgnoringCase("[0] String")
+                    .containsIgnoringCase("position")
+                    .contains("30");
+        }
+    }
+
+    @Test
+    public void should_fail_if_index_is_not_in_range_for_example_with_no_arg_invocation() throws Throwable {
+        try {
+            new ReturnsArgumentAt(ReturnsArgumentAt.LAST_ARGUMENT).validateFor(
+                    new InvocationBuilder().simpleMethod().toInvocation()
+            );
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage())
+                    .containsIgnoringCase("invalid argument index")
+                    .containsIgnoringCase("iMethods.simpleMethod")
+                    .containsIgnoringCase("no arguments")
+                    .containsIgnoringCase("last parameter wanted");
+        }
+    }
+
+    @Test
+    public void should_fail_if_argument_type_of_signature_is_incompatible_with_return_type() throws Throwable {
+        try {
+            new ReturnsArgumentAt(2).validateFor(
+                    new InvocationBuilder().method("varargsReturningString")
+                                           .argTypes(Object[].class)
+                                           .args("anyString", new Object(), "anyString")
+                                           .toInvocation()
+            );
+            fail();
+        } catch (WrongTypeOfReturnValue e) {
+            assertThat(e.getMessage())
+                    .containsIgnoringCase("argument of type")
+                    .containsIgnoringCase("Object")
+                    .containsIgnoringCase("varargsReturningString")
+                    .containsIgnoringCase("should return")
+                    .containsIgnoringCase("String")
+                    .containsIgnoringCase("possible argument indexes");
+        }
+    }
+
+    private static InvocationOnMock invocationWith(Object... parameters) {
+        return new InvocationBuilder().method("varargsReturningString")
+                                      .argTypes(Object[].class)
+                                      .args(parameters).toInvocation();
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/ReturnsTest.java b/src/test/java/org/mockito/internal/stubbing/answers/ReturnsTest.java
new file mode 100644
index 0000000..b4d6b43
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/ReturnsTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationBuilder;
+
+import static java.lang.Boolean.TRUE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ReturnsTest {
+    @Test
+    public void should_return_value() throws Throwable {
+        assertThat(new Returns("value").answer(new InvocationBuilder().method("oneArg").arg("A").toInvocation())).isEqualTo("value");
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_when_return_Value_is_set_for_void_method() throws Throwable {
+        new Returns("one").validateFor(new InvocationBuilder().method("voidMethod").toInvocation());
+    }
+
+    @Test
+    public void should_allow_correct_type_of_return_value() throws Throwable {
+        new Returns("one").validateFor(new InvocationBuilder().simpleMethod().toInvocation());
+        new Returns(false).validateFor(new InvocationBuilder().method("booleanReturningMethod").toInvocation());
+        new Returns(TRUE).validateFor(new InvocationBuilder().method("booleanObjectReturningMethod").toInvocation());
+        new Returns(1).validateFor(new InvocationBuilder().method("integerReturningMethod").toInvocation());
+        new Returns(1L).validateFor(new InvocationBuilder().method("longReturningMethod").toInvocation());
+        new Returns(1L).validateFor(new InvocationBuilder().method("longObjectReturningMethod").toInvocation());
+        new Returns(null).validateFor(new InvocationBuilder().method("objectReturningMethodNoArgs").toInvocation());
+        new Returns(1).validateFor(new InvocationBuilder().method("objectReturningMethodNoArgs").toInvocation());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_on_return_type_mismatch() throws Throwable {
+        new Returns("String").validateFor(new InvocationBuilder().method("booleanReturningMethod").toInvocation());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_on_wrong_primitive() throws Throwable {
+        new Returns(1).validateFor(new InvocationBuilder().method("doubleReturningMethod").toInvocation());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_on_null_with_primitive() throws Throwable {
+        new Returns(null).validateFor(new InvocationBuilder().method("booleanReturningMethod").toInvocation());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java b/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java
new file mode 100644
index 0000000..4406499
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java
@@ -0,0 +1,78 @@
+package org.mockito.internal.stubbing.answers;
+
+import java.io.IOException;
+import java.nio.charset.CharacterCodingException;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+
+public class ThrowsExceptionTest {
+    @Test
+    public void should_raise_wanted_throwable() throws Throwable {
+        try {
+            new ThrowsException(new IllegalStateException("my dear throwable")).answer(new InvocationBuilder().method("canThrowException").toInvocation());
+            Assertions.fail("should have raised wanted exception");
+        } catch (Throwable throwable) {
+            assertThat(throwable).isInstanceOf(IllegalStateException.class).hasMessage("my dear throwable");
+        }
+    }
+
+    @Test
+    public void should_throw_mock_exception_without_stacktrace() throws Exception {
+        try {
+            new ThrowsException(mock(Exception.class)).answer(new InvocationBuilder().method("canThrowException").toInvocation());
+            Assertions.fail("should have raised wanted exception");
+        } catch (Throwable throwable) {
+            assertThat(throwable.getStackTrace()).describedAs("no stack trace, it's mock").isNull();
+        }
+    }
+
+    @Test
+    public void should_fill_in_exception_stacktrace() throws Exception {
+        // given
+        Exception throwableToRaise = new Exception();
+        throwableToRaise.fillInStackTrace();
+        assertThat(throwableToRaise.getStackTrace()[0].getClassName()).isEqualTo(this.getClass().getName());
+        assertThat(throwableToRaise.getStackTrace()[0].getMethodName()).isEqualTo("should_fill_in_exception_stacktrace");
+        try {
+
+            // when
+            new ThrowsException(throwableToRaise).answer(new InvocationBuilder().method("canThrowException").toInvocation());
+            Assertions.fail("should have raised wanted exception");
+        } catch (Throwable throwable) {
+            // then
+            throwable.printStackTrace();
+            assertThat(throwableToRaise.getStackTrace()[0].getClassName()).isEqualTo(ThrowsException.class.getName());
+            assertThat(throwableToRaise.getStackTrace()[0].getMethodName()).isEqualTo("answer");
+        }
+    }
+
+    @Test
+    public void should_invalidate_null_throwable() throws Throwable {
+        try {
+            new ThrowsException(null).validateFor(new InvocationBuilder().toInvocation());
+            Assertions.fail("should have raised a MockitoException");
+        } catch (MockitoException expected) {}
+    }
+
+    @Test
+    public void should_pass_proper_checked_exception() throws Throwable {
+        new ThrowsException(new CharacterCodingException()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_invalid_checked_exception() throws Throwable {
+        new ThrowsException(new IOException()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+    }
+
+    @Test
+    public void should_pass_RuntimeExceptions() throws Throwable {
+        new ThrowsException(new Error()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+        new ThrowsException(new RuntimeException()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocationsTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocationsTest.java
new file mode 100644
index 0000000..6a7f04b
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocationsTest.java
@@ -0,0 +1,32 @@
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class ForwardsInvocationsTest extends TestBase {
+
+    interface Foo {
+        int bar(String baz, Object... args);
+    }
+
+    private static final class FooImpl implements Foo {
+        @Override
+        public int bar(String baz, Object... args) {
+            return baz.length() + args.length;
+        }
+    }
+
+    @Test
+    public void should_call_method_with_varargs() throws Throwable {
+        ForwardsInvocations forwardsInvocations = new ForwardsInvocations(new FooImpl());
+        assertEquals(4, forwardsInvocations.answer(invocationOf(Foo.class, "bar", "b", new Object[] {12, "3", 4.5})));
+    }
+
+    @Test
+    public void should_call_method_with_empty_varargs() throws Throwable {
+        ForwardsInvocations forwardsInvocations = new ForwardsInvocations(new FooImpl());
+        assertEquals(1, forwardsInvocations.answer(invocationOf(Foo.class, "bar", "b", new Object[] {})));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/HasPrimitiveMethods.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/HasPrimitiveMethods.java
new file mode 100755
index 0000000..9aaea02
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/HasPrimitiveMethods.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+@SuppressWarnings("unused")
+interface HasPrimitiveMethods {
+    boolean booleanMethod();
+    char charMethod();
+    byte byteMethod();
+    short shortMethod();
+    int intMethod();
+    long longMethod();
+    float floatMethod();
+    double doubleMethod();
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValuesTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValuesTest.java
new file mode 100644
index 0000000..ab9aad9
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValuesTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.mockito.invocation.Invocation;
+import org.mockitoutil.TestBase;
+
+import java.util.*;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.mock;
+
+public class ReturnsEmptyValuesTest extends TestBase {
+
+    private final ReturnsEmptyValues values = new ReturnsEmptyValues();
+
+    @Test
+    public void should_return_empty_collections_or_null_for_non_collections() {
+        assertTrue(((Collection<?>) values.returnValueFor(Collection.class)).isEmpty());
+
+        assertTrue(((Set<?>) values.returnValueFor(Set.class)).isEmpty());
+        assertTrue(((SortedSet<?>) values.returnValueFor(SortedSet.class)).isEmpty());
+        assertTrue(((HashSet<?>) values.returnValueFor(HashSet.class)).isEmpty());
+        assertTrue(((TreeSet<?>) values.returnValueFor(TreeSet.class)).isEmpty());
+        assertTrue(((LinkedHashSet<?>) values.returnValueFor(LinkedHashSet.class)).isEmpty());
+
+        assertTrue(((List<?>) values.returnValueFor(List.class)).isEmpty());
+        assertTrue(((ArrayList<?>) values.returnValueFor(ArrayList.class)).isEmpty());
+        assertTrue(((LinkedList<?>) values.returnValueFor(LinkedList.class)).isEmpty());
+
+        assertTrue(((Map<?, ?>) values.returnValueFor(Map.class)).isEmpty());
+        assertTrue(((SortedMap<?, ?>) values.returnValueFor(SortedMap.class)).isEmpty());
+        assertTrue(((HashMap<?, ?>) values.returnValueFor(HashMap.class)).isEmpty());
+        assertTrue(((TreeMap<?, ?>) values.returnValueFor(TreeMap.class)).isEmpty());
+        assertTrue(((LinkedHashMap<?, ?>) values.returnValueFor(LinkedHashMap.class)).isEmpty());
+
+        assertNull(values.returnValueFor(String.class));
+    }
+
+    @Test
+    public void should_return_empty_iterable() throws Exception {
+        assertFalse(((Iterable<?>) values.returnValueFor(Iterable.class)).iterator().hasNext());
+    }
+
+    @Test
+    public void should_return_primitive() {
+        assertEquals(false, values.returnValueFor(Boolean.TYPE));
+        assertEquals((char) 0, values.returnValueFor(Character.TYPE));
+        assertEquals((byte) 0, values.returnValueFor(Byte.TYPE));
+        assertEquals((short) 0, values.returnValueFor(Short.TYPE));
+        assertEquals(0, values.returnValueFor(Integer.TYPE));
+        assertEquals(0L, values.returnValueFor(Long.TYPE));
+        assertEquals(0F, values.returnValueFor(Float.TYPE));
+        assertEquals(0D, values.returnValueFor(Double.TYPE));
+    }
+
+    @Test
+    public void should_return_non_zero_for_compareTo_method() {
+        //
+        // given
+        Date d = mock(Date.class);
+        d.compareTo(new Date());
+        Invocation compareTo = this.getLastInvocation();
+
+        //when
+        Object result = values.answer(compareTo);
+
+        //then
+        assertTrue(result != (Object) 0);
+    }
+
+    @Test
+    public void should_return_zero_if_mock_is_compared_to_itself() {
+        //given
+        Date d = mock(Date.class);
+        d.compareTo(d);
+        Invocation compareTo = this.getLastInvocation();
+
+        //when
+        Object result = values.answer(compareTo);
+
+        //then
+        assertEquals(0, result);
+    }
+
+    @Test
+    public void should_return_empty_Optional() throws Exception {
+        verify_empty_Optional_is_returned("java.util.stream.Stream", "java.util.Optional");
+    }
+
+    @Test
+    public void should_return_empty_OptionalDouble() throws Exception {
+        verify_empty_Optional_is_returned("java.util.stream.DoubleStream", "java.util.OptionalDouble");
+    }
+
+    @Test
+    public void should_return_empty_OptionalInt() throws Exception {
+        verify_empty_Optional_is_returned("java.util.stream.IntStream", "java.util.OptionalInt");
+    }
+
+    @Test
+    public void should_return_empty_OptionalLong() throws Exception {
+        verify_empty_Optional_is_returned("java.util.stream.LongStream", "java.util.OptionalLong");
+    }
+
+    private void verify_empty_Optional_is_returned(String streamFqcn, String optionalFqcn) throws Exception {
+        Class<?> streamType = getClassOrSkipTest(streamFqcn);
+
+        //given
+        Object stream = mock(streamType);
+        Object optional = streamType.getMethod("findAny").invoke(stream);
+        assertNotNull(optional);
+        assertFalse((Boolean) Class.forName(optionalFqcn).getMethod("isPresent").invoke(optional));
+
+        Invocation findAny = this.getLastInvocation();
+
+        //when
+        Object result = values.answer(findAny);
+
+        //then
+        assertEquals(optional, result);
+    }
+
+    @Test
+    public void should_return_empty_Stream() throws Exception {
+        verify_empty_Stream_is_returned("java.util.stream.Stream");
+    }
+
+    @Test
+    public void should_return_empty_DoubleStream() throws Exception {
+        verify_empty_Stream_is_returned("java.util.stream.DoubleStream");
+    }
+
+    @Test
+    public void should_return_empty_IntStream() throws Exception {
+        verify_empty_Stream_is_returned("java.util.stream.IntStream");
+    }
+
+    @Test
+    public void should_return_empty_LongStream() throws Exception {
+        verify_empty_Stream_is_returned("java.util.stream.LongStream");
+    }
+
+    private void verify_empty_Stream_is_returned(String streamFqcn) throws Exception {
+        // given
+        Class<?> streamType = getClassOrSkipTest(streamFqcn);
+
+        // when
+        Object stream = values.returnValueFor(streamType);
+        long count = (Long) streamType.getMethod("count").invoke(stream);
+
+        // then
+        assertEquals("count of empty " + streamFqcn, 0L, count);
+    }
+
+    /**
+     * Tries to load the given class. If the class is not found, the complete test is skipped.
+     */
+    private Class<?> getClassOrSkipTest(String className) {
+        try {
+            return Class.forName(className);
+        } catch (ClassNotFoundException e) {
+            Assume.assumeNoException("JVM does not support " + className, e);
+            return null;
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsGenericDeepStubsTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsGenericDeepStubsTest.java
new file mode 100644
index 0000000..d91df8c
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsGenericDeepStubsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+@SuppressWarnings("unused")
+public class ReturnsGenericDeepStubsTest {
+    interface ListOfInteger extends List<Integer> {}
+
+    interface AnotherListOfInteger extends ListOfInteger {}
+
+    interface GenericsNest<K extends Comparable<K> & Cloneable> extends Map<K, Set<Number>> {
+        Set<Number> remove(Object key); // override with fixed ParameterizedType
+        List<? super Number> returningWildcard();
+        Map<String, K> returningNonMockableNestedGeneric();
+        K returningK();
+        <O extends K> List<O> paramTypeWithTypeParams();
+        <S extends Appendable, T extends S> T twoTypeParams(S s);
+        <O extends K> O typeVarWithTypeParams();
+        Number returnsNormalType();
+    }
+
+    @Test
+    public void generic_deep_mock_frenzy__look_at_these_chained_calls() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        Set<? extends Map.Entry<? extends Cloneable, Set<Number>>> entries = mock.entrySet();
+        Iterator<? extends Map.Entry<? extends Cloneable,Set<Number>>> entriesIterator = mock.entrySet().iterator();
+        Map.Entry<? extends Cloneable, Set<Number>> nextEntry = mock.entrySet().iterator().next();
+
+        Cloneable cloneableKey = mock.entrySet().iterator().next().getKey();
+        Comparable<?> comparableKey = mock.entrySet().iterator().next().getKey();
+
+        Set<Number> value = mock.entrySet().iterator().next().getValue();
+        Iterator<Number> numbersIterator = mock.entrySet().iterator().next().getValue().iterator();
+        Number number = mock.entrySet().iterator().next().getValue().iterator().next();
+    }
+
+    @Test
+    public void can_create_mock_from_multiple_type_variable_bounds_when_return_type_of_parameterized_method_is_a_parameterizedtype_that_is_referencing_a_typevar_on_class() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        Cloneable cloneable_bound_that_is_declared_on_typevar_K_in_the_class_which_is_referenced_by_typevar_O_declared_on_the_method =
+                mock.paramTypeWithTypeParams().get(0);
+        Comparable<?> comparable_bound_that_is_declared_on_typevar_K_in_the_class_which_is_referenced_by_typevar_O_declared_on_the_method =
+                mock.paramTypeWithTypeParams().get(0);
+    }
+
+    @Test
+    public void can_create_mock_from_multiple_type_variable_bounds_when_method_return_type_is_referencing_a_typevar_on_class() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        Cloneable cloneable_bound_of_typevar_K = mock.returningK();
+        Comparable<?> comparable_bound_of_typevar_K = mock.returningK();
+    }
+
+    @Test
+    public void can_create_mock_from_multiple_type_variable_bounds_when_return_type_of_parameterized_method_is_a_typevar_that_is_referencing_a_typevar_on_class() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        Cloneable cloneable_bound_of_typevar_K_referenced_by_typevar_O = (Cloneable) mock.typeVarWithTypeParams();
+        Comparable<?> comparable_bound_of_typevar_K_referenced_by_typevar_O = (Comparable<?>) mock.typeVarWithTypeParams();
+    }
+
+    @Test
+    public void can_create_mock_from_return_types_declared_with_a_bounded_wildcard() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        List<? super Integer> objects = mock.returningWildcard();
+        Number type_that_is_the_upper_bound_of_the_wildcard = (Number) mock.returningWildcard().get(45);
+        type_that_is_the_upper_bound_of_the_wildcard.floatValue();
+    }
+
+    @Test
+    public void can_still_work_with_raw_type_in_the_return_type() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        Number the_raw_type_that_should_be_returned = mock.returnsNormalType();
+        the_raw_type_that_should_be_returned.floatValue();
+    }
+
+    @Test
+    public void will_return_default_value_on_non_mockable_nested_generic() throws Exception {
+        GenericsNest<?> genericsNest = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+        ListOfInteger listOfInteger = mock(ListOfInteger.class, RETURNS_DEEP_STUBS);
+        AnotherListOfInteger anotherListOfInteger = mock(AnotherListOfInteger.class, RETURNS_DEEP_STUBS);
+
+        assertThat(genericsNest.returningNonMockableNestedGeneric().keySet().iterator().next()).isNull();
+        assertThat(listOfInteger.get(25)).isEqualTo(0);
+        assertThat(anotherListOfInteger.get(25)).isEqualTo(0);
+    }
+
+    @Test(expected = ClassCastException.class)
+    public void as_expected_fail_with_a_CCE_on_callsite_when_erasure_takes_place_for_example___StringBuilder_is_subject_to_erasure() throws Exception {
+        GenericsNest<?> mock = mock(GenericsNest.class, RETURNS_DEEP_STUBS);
+
+        // following assignment needed to create a ClassCastException on the call site (i.e. : here)
+        StringBuilder stringBuilder_assignment_that_should_throw_a_CCE =
+                mock.twoTypeParams(new StringBuilder()).append(2).append(3);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocksTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocksTest.java
new file mode 100755
index 0000000..4cb32e7
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocksTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.junit.Test;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.internal.util.MockUtil;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+import static org.junit.Assume.assumeFalse;
+
+public class ReturnsMocksTest extends TestBase {
+    private ReturnsMocks values = new ReturnsMocks();
+
+    interface FooInterface {
+    }
+
+    class BarClass {
+    }
+
+    final class Baz {
+    }
+
+    @Test
+    public void should_return_mock_value_for_interface() throws Exception {
+        Object interfaceMock = values.returnValueFor(FooInterface.class);
+        assertTrue(MockUtil.isMock(interfaceMock));
+    }
+
+    @Test
+    public void should_return_mock_value_for_class() throws Exception {
+        Object classMock = values.returnValueFor(BarClass.class);
+        assertTrue(MockUtil.isMock(classMock));
+    }
+
+    @Test
+    public void should_return_null_for_final_class_if_unsupported() throws Exception {
+        assumeFalse(Plugins.getMockMaker().isTypeMockable(Baz.class).mockable());
+        assertNull(values.returnValueFor(Baz.class));
+    }
+
+    @Test
+    public void should_return_the_usual_default_values_for_primitives() throws Throwable {
+        ReturnsMocks answer = new ReturnsMocks();
+        assertEquals(false, answer.answer(invocationOf(HasPrimitiveMethods.class, "booleanMethod")));
+        assertEquals((char) 0, answer.answer(invocationOf(HasPrimitiveMethods.class, "charMethod")));
+        assertEquals((byte) 0, answer.answer(invocationOf(HasPrimitiveMethods.class, "byteMethod")));
+        assertEquals((short) 0, answer.answer(invocationOf(HasPrimitiveMethods.class, "shortMethod")));
+        assertEquals(0, answer.answer(invocationOf(HasPrimitiveMethods.class, "intMethod")));
+        assertEquals(0L, answer.answer(invocationOf(HasPrimitiveMethods.class, "longMethod")));
+        assertEquals(0f, answer.answer(invocationOf(HasPrimitiveMethods.class, "floatMethod")));
+        assertEquals(0d, answer.answer(invocationOf(HasPrimitiveMethods.class, "doubleMethod")));
+    }
+
+    @SuppressWarnings("unused")
+    interface StringMethods {
+        String stringMethod();
+        String[] stringArrayMethod();
+    }
+
+    @Test
+    public void should_return_empty_array() throws Throwable {
+        String[] ret = (String[]) values.answer(invocationOf(StringMethods.class, "stringArrayMethod"));
+
+        assertTrue(ret.getClass().isArray());
+        assertTrue(ret.length == 0);
+    }
+
+    @Test
+    public void should_return_empty_string() throws Throwable {
+        assertEquals("", values.answer(invocationOf(StringMethods.class, "stringMethod")));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValuesTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValuesTest.java
new file mode 100644
index 0000000..4e3d472
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValuesTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+public class ReturnsMoreEmptyValuesTest extends TestBase {
+
+    private ReturnsMoreEmptyValues rv = new ReturnsMoreEmptyValues();
+
+    @Test
+    public void shouldReturnEmptyArray() {
+        String[] ret = (String[]) rv.returnValueFor((new String[0]).getClass());
+        assertTrue(ret.getClass().isArray());
+        assertTrue(ret.length == 0);
+    }
+
+    @Test
+    public void shouldReturnEmptyString() {
+        assertEquals("", rv.returnValueFor(String.class));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNullsTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNullsTest.java
new file mode 100644
index 0000000..a2e33f8
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNullsTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.mockito.exceptions.verification.SmartNullPointerException;
+import org.mockito.stubbing.Answer;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+
+public class ReturnsSmartNullsTest extends TestBase {
+
+    @Test
+    public void should_return_the_usual_default_values_for_primitives() throws Throwable {
+        Answer<Object> answer = new ReturnsSmartNulls();
+        assertEquals(false  ,   answer.answer(invocationOf(HasPrimitiveMethods.class, "booleanMethod")));
+        assertEquals((char) 0,  answer.answer(invocationOf(HasPrimitiveMethods.class, "charMethod")));
+        assertEquals((byte) 0,  answer.answer(invocationOf(HasPrimitiveMethods.class, "byteMethod")));
+        assertEquals((short) 0, answer.answer(invocationOf(HasPrimitiveMethods.class, "shortMethod")));
+        assertEquals(0,         answer.answer(invocationOf(HasPrimitiveMethods.class, "intMethod")));
+        assertEquals(0L,        answer.answer(invocationOf(HasPrimitiveMethods.class, "longMethod")));
+        assertEquals(0f,        answer.answer(invocationOf(HasPrimitiveMethods.class, "floatMethod")));
+        assertEquals(0d,        answer.answer(invocationOf(HasPrimitiveMethods.class, "doubleMethod")));
+    }
+
+    @SuppressWarnings("unused")
+    interface Foo {
+        Foo get();
+        Foo withArgs(String oneArg, String otherArg);
+    }
+
+    @Test
+    public void should_return_an_object_that_fails_on_any_method_invocation_for_non_primitives() throws Throwable {
+        Answer<Object> answer = new ReturnsSmartNulls();
+
+        Foo smartNull = (Foo) answer.answer(invocationOf(Foo.class, "get"));
+
+        try {
+            smartNull.get();
+            fail();
+        } catch (SmartNullPointerException expected) {}
+    }
+
+    @Test
+    public void should_return_an_object_that_allows_object_methods() throws Throwable {
+        Answer<Object> answer = new ReturnsSmartNulls();
+
+        Foo smartNull = (Foo) answer.answer(invocationOf(Foo.class, "get"));
+
+        assertThat(smartNull.toString())
+            .contains("SmartNull returned by")
+            .contains("foo.get()");
+    }
+
+    @Test
+    public void should_print_the_parameters_when_calling_a_method_with_args() throws Throwable {
+        Answer<Object> answer = new ReturnsSmartNulls();
+
+        Foo smartNull = (Foo) answer.answer(invocationOf(Foo.class, "withArgs", "oompa", "lumpa"));
+
+        assertThat(smartNull.toString())
+            .contains("foo.withArgs")
+            .contains("oompa")
+            .contains("lumpa");
+    }
+
+    @Test
+    public void should_print_the_parameters_on_SmartNullPointerException_message() throws Throwable {
+        Answer<Object> answer = new ReturnsSmartNulls();
+
+        Foo smartNull = (Foo) answer.answer(invocationOf(Foo.class, "withArgs", "oompa", "lumpa"));
+
+        try {
+            smartNull.get();
+            fail();
+        } catch (SmartNullPointerException e) {
+            assertThat(e)
+                .hasMessageContaining("oompa")
+                .hasMessageContaining("lumpa");
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/DecamelizerTest.java b/src/test/java/org/mockito/internal/util/DecamelizerTest.java
new file mode 100644
index 0000000..cb0b4a8
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/DecamelizerTest.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.internal.util.Decamelizer.decamelizeMatcher;
+
+public class DecamelizerTest extends TestBase {
+
+    @Test
+    public void shouldProduceDecentDescription() throws Exception {
+        assertEquals("<Sentence with strong language>", decamelizeMatcher("SentenceWithStrongLanguage"));
+        assertEquals("<W e i r d o 1>", decamelizeMatcher("WEIRDO1"));
+        assertEquals("<_>", decamelizeMatcher("_"));
+        assertEquals("<Has exactly 3 elements>", decamelizeMatcher("HasExactly3Elements"));
+        assertEquals("<custom argument matcher>", decamelizeMatcher(""));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/DefaultMockingDetailsTest.java b/src/test/java/org/mockito/internal/util/DefaultMockingDetailsTest.java
new file mode 100644
index 0000000..8af561b
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/DefaultMockingDetailsTest.java
@@ -0,0 +1,198 @@
+package org.mockito.internal.util;
+
+import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.stubbing.Stubbing;
+import org.mockitousage.IMethods;
+
+import java.util.Collection;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+@SuppressWarnings("unchecked")
+public class DefaultMockingDetailsTest {
+
+    @Mock private Foo foo;
+    @Mock private Bar bar;
+    @Mock private IMethods mock;
+    @Spy private Gork gork;
+
+    @Before public void before() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void should_know_spy(){
+        assertTrue(mockingDetails(gork).isMock());
+        assertTrue(mockingDetails(spy( new Gork())).isMock());
+        assertTrue(mockingDetails(spy(Gork.class)).isMock());
+        assertTrue(mockingDetails(mock(Gork.class, withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))).isMock());
+    }
+
+    @Test
+    public void should_know_mock(){
+        assertTrue(mockingDetails(foo).isMock());
+        assertTrue(mockingDetails(mock(Foo.class)).isMock());
+        assertFalse(mockingDetails(foo).isSpy());
+        assertFalse(mockingDetails(mock(Foo.class)).isSpy());
+    }
+
+    @Test
+    public void should_handle_non_mocks() {
+        assertFalse(mockingDetails("non mock").isSpy());
+        assertFalse(mockingDetails("non mock").isMock());
+
+        assertFalse(mockingDetails(null).isSpy());
+        assertFalse(mockingDetails(null).isMock());
+    }
+
+    @Test
+    public void should_check_that_a_spy_is_also_a_mock() throws Exception {
+        assertEquals(true, mockingDetails(gork).isMock());
+    }
+
+    @Test
+    public void provides_invocations() {
+        //when
+        mock.simpleMethod(10);
+        mock.otherMethod();
+
+        //then
+        assertEquals(0, mockingDetails(foo).getInvocations().size());
+        assertEquals("[mock.simpleMethod(10);, mock.otherMethod();]", mockingDetails(mock).getInvocations().toString());
+    }
+
+    @Test
+    public void manipulating_invocations_is_safe() {
+        mock.simpleMethod();
+
+        //when we manipulate the invocations
+        mockingDetails(mock).getInvocations().clear();
+
+        //then we didn't actually changed the invocations
+        assertEquals(1, mockingDetails(mock).getInvocations().size());
+    }
+
+    @Test
+    public void provides_mock_creation_settings() {
+        //smoke test some creation settings
+        assertEquals(Foo.class, mockingDetails(foo).getMockCreationSettings().getTypeToMock());
+        assertEquals(Bar.class, mockingDetails(bar).getMockCreationSettings().getTypeToMock());
+        assertEquals(0, mockingDetails(mock).getMockCreationSettings().getExtraInterfaces().size());
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void fails_when_getting_creation_settings_for_incorrect_input() {
+        mockingDetails(null).getMockCreationSettings();
+    }
+
+    @Test
+    public void fails_when_getting_invocations_when_null() {
+        try {
+            //when
+            mockingDetails(null).getInvocations();
+            //then
+            fail();
+        } catch (NotAMockException e) {
+            TestCase.assertEquals("Argument passed to Mockito.mockingDetails() should be a mock, but is null!", e.getMessage());
+        }
+    }
+
+    @Test
+    public void fails_when_getting_invocations_when_not_mock() {
+        try {
+            //when
+            mockingDetails(new Object()).getInvocations();
+            //then
+            fail();
+        } catch (NotAMockException e) {
+            TestCase.assertEquals("Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class java.lang.Object!", e.getMessage());
+        }
+    }
+
+    @Test
+    public void fails_when_getting_stubbings_from_non_mock() {
+        try {
+            //when
+            mockingDetails(new Object()).getStubbings();
+            //then
+            fail();
+        } catch (NotAMockException e) {
+            TestCase.assertEquals("Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class java.lang.Object!", e.getMessage());
+        }
+    }
+
+    @Test
+    public void mock_with_no_stubbings() {
+        assertTrue(mockingDetails(mock).getStubbings().isEmpty());
+    }
+
+    @Test
+    public void provides_stubbings_of_mock_in_declaration_order() {
+        when(mock.simpleMethod(1)).thenReturn("1");
+        when(mock.otherMethod()).thenReturn("2");
+
+        //when
+        Collection<Stubbing> stubbings = mockingDetails(mock).getStubbings();
+
+        //then
+        assertEquals(2, stubbings.size());
+        assertEquals("[mock.simpleMethod(1); stubbed with: [Returns: 1], mock.otherMethod(); stubbed with: [Returns: 2]]", stubbings.toString());
+    }
+
+    @Test
+    public void manipulating_stubbings_explicitly_is_safe() {
+        when(mock.simpleMethod(1)).thenReturn("1");
+
+        //when somebody manipulates stubbings directly
+        mockingDetails(mock).getStubbings().clear();
+
+        //then it does not affect stubbings of the mock
+        assertEquals(1, mockingDetails(mock).getStubbings().size());
+    }
+
+    @Test
+    public void prints_invocations() throws Exception {
+        //given
+        given(mock.simpleMethod("different arg")).willReturn("foo");
+        mock.simpleMethod("arg");
+
+        //when
+        String log = Mockito.mockingDetails(mock).printInvocations();
+
+        //then
+        assertThat(log).containsIgnoringCase("unused");
+        assertThat(log).containsIgnoringCase("mock.simpleMethod(\"arg\")");
+        assertThat(log).containsIgnoringCase("mock.simpleMethod(\"different arg\")");
+    }
+
+    @Test
+    public void fails_when_printin_invocations_from_non_mock() {
+        try {
+            //when
+            mockingDetails(new Object()).printInvocations();
+            //then
+            fail();
+        } catch (NotAMockException e) {
+            TestCase.assertEquals("Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class java.lang.Object!", e.getMessage());
+        }
+    }
+
+    public class Foo { }
+    public interface Bar { }
+    public static class Gork { }
+}
diff --git a/src/test/java/org/mockito/internal/util/MockCreationValidatorTest.java b/src/test/java/org/mockito/internal/util/MockCreationValidatorTest.java
new file mode 100644
index 0000000..1a9b109
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/MockCreationValidatorTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+@SuppressWarnings("unchecked")
+public class MockCreationValidatorTest {
+
+    MockCreationValidator validator = new MockCreationValidator();
+
+    @Test
+    public void should_not_allow_extra_interface_that_is_the_same_as_the_mocked_type() throws Exception {
+        try {
+            //when
+            validator.validateExtraInterfaces(IMethods.class, (Collection) asList(IMethods.class));
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e.getMessage()).contains("You mocked following type: IMethods");
+        }
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_not_allow_inconsistent_types() throws Exception {
+        //when
+        validator.validateMockedType(List.class, new ArrayList());
+        //then
+    }
+
+    @Test
+    public void should_allow_only_consistent_types() throws Exception {
+        //when
+        validator.validateMockedType(ArrayList.class, new ArrayList());
+        //then no exception is thrown
+    }
+
+    @Test
+    public void should_validation_be_safe_when_nulls_passed() throws Exception {
+        //when
+        validator.validateMockedType(null, new ArrayList());
+        //or
+        validator.validateMockedType(ArrayList.class, null);
+        //then no exception is thrown
+    }
+
+    @Test
+    public void should_fail_when_type_not_mockable() throws Exception {
+        try {
+            validator.validateType(long.class);
+        } catch (MockitoException ex) {
+            assertThat(ex.getMessage()).contains("primitive");
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/MockNameImplTest.java b/src/test/java/org/mockito/internal/util/MockNameImplTest.java
new file mode 100644
index 0000000..6ba7637
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/MockNameImplTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class MockNameImplTest extends TestBase {
+
+    @Test
+    public void shouldProvideTheNameForClass() throws Exception {
+        //when
+        String name = new MockNameImpl(null, SomeClass.class).toString();
+        //then
+        assertEquals("someClass", name);
+    }
+
+    @Test
+    public void shouldProvideTheNameForAnonymousClass() throws Exception {
+        //given
+        SomeInterface anonymousInstance = new SomeInterface() {};
+        //when
+        String name = new MockNameImpl(null, anonymousInstance.getClass()).toString();
+        //then
+        assertEquals("someInterface", name);
+    }
+
+    @Test
+    public void shouldProvideTheGivenName() throws Exception {
+        //when
+        String name = new MockNameImpl("The Hulk", SomeClass.class).toString();
+        //then
+        assertEquals("The Hulk", name);
+    }
+
+    private class SomeClass {}
+    private class SomeInterface {}
+}
diff --git a/src/test/java/org/mockito/internal/util/MockUtilTest.java b/src/test/java/org/mockito/internal/util/MockUtilTest.java
new file mode 100644
index 0000000..9b3801d
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/MockUtilTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockitoutil.TestBase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.withSettings;
+
+@SuppressWarnings("unchecked")
+public class MockUtilTest extends TestBase {
+
+    @Test
+    public void should_get_handler() {
+        List<?> mock = Mockito.mock(List.class);
+        assertNotNull(MockUtil.getMockHandler(mock));
+    }
+
+    @Test (expected=NotAMockException.class)
+    public void should_scream_when_not_a_mock_passed() {
+        MockUtil.getMockHandler("");
+    }
+
+    @Test (expected=MockitoException.class)
+    public void should_scream_when_null_passed() {
+        MockUtil.getMockHandler(null);
+    }
+
+    @Test
+    public void should_get_mock_settings() {
+        List<?> mock = Mockito.mock(List.class);
+        assertNotNull(MockUtil.getMockSettings(mock));
+    }
+
+    @Test
+    public void should_validate_mock() {
+        assertFalse(MockUtil.isMock("i mock a mock"));
+        assertTrue(MockUtil.isMock(Mockito.mock(List.class)));
+    }
+
+    @Test
+    public void should_validate_spy() {
+        assertFalse(MockUtil.isSpy("i mock a mock"));
+        assertFalse(MockUtil.isSpy(Mockito.mock(List.class)));
+        assertFalse(MockUtil.isSpy(null));
+
+        assertTrue(MockUtil.isSpy(Mockito.spy(new ArrayList())));
+        assertTrue(MockUtil.isSpy(Mockito.spy(ArrayList.class)));
+        assertTrue(MockUtil.isSpy(Mockito.mock(ArrayList.class, withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))));
+    }
+
+    @Test
+    public void should_redefine_MockName_if_default() {
+        List<?> mock = Mockito.mock(List.class);
+        MockUtil.maybeRedefineMockName(mock, "newName");
+
+        Assertions.assertThat(MockUtil.getMockName(mock).toString()).isEqualTo("newName");
+    }
+
+    @Test
+    public void should_not_redefine_MockName_if_default() {
+        List<?> mock = Mockito.mock(List.class, "original");
+        MockUtil.maybeRedefineMockName(mock, "newName");
+
+        Assertions.assertThat(MockUtil.getMockName(mock).toString()).isEqualTo("original");
+    }
+
+    final class FinalClass {}
+    class SomeClass {}
+    interface SomeInterface {}
+
+    @Test
+    public void should_know_if_type_is_mockable() throws Exception {
+        Assertions.assertThat(MockUtil.typeMockabilityOf(FinalClass.class).mockable())
+                .isEqualTo(Plugins.getMockMaker().isTypeMockable(FinalClass.class).mockable());
+
+        assertFalse(MockUtil.typeMockabilityOf(int.class).mockable());
+
+        assertTrue(MockUtil.typeMockabilityOf(SomeClass.class).mockable());
+        assertTrue(MockUtil.typeMockabilityOf(SomeInterface.class).mockable());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/ObjectMethodsGuruTest.java b/src/test/java/org/mockito/internal/util/ObjectMethodsGuruTest.java
new file mode 100644
index 0000000..53db710
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/ObjectMethodsGuruTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.junit.Test;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.Date;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+public class ObjectMethodsGuruTest extends TestBase {
+
+
+    private interface HasCompareToButDoesNotImplementComparable {
+        int compareTo(HasCompareToButDoesNotImplementComparable other);
+    }
+
+    private interface HasCompare extends Comparable<HasCompare> {
+        int foo(HasCompare other);
+        int compareTo(HasCompare other, String redHerring);
+        int compareTo(String redHerring);
+        int compareTo(HasCompare redHerring);
+    }
+
+    @Test
+    public void shouldKnowToStringMethod() throws Exception {
+        assertFalse(ObjectMethodsGuru.isToStringMethod(Object.class.getMethod("equals", Object.class)));
+        assertFalse(ObjectMethodsGuru.isToStringMethod(IMethods.class.getMethod("toString", String.class)));
+        assertTrue(ObjectMethodsGuru.isToStringMethod(IMethods.class.getMethod("toString")));
+    }
+
+
+    @Test
+    public void shouldKnowCompareToMethod() throws Exception {
+        assertFalse(ObjectMethodsGuru.isCompareToMethod(Date.class.getMethod("toString")));
+        assertFalse(ObjectMethodsGuru.isCompareToMethod(HasCompare.class.getMethod("foo", HasCompare.class)));
+        assertFalse(ObjectMethodsGuru.isCompareToMethod(HasCompare.class.getMethod("compareTo", HasCompare.class, String.class)));
+        assertFalse(ObjectMethodsGuru.isCompareToMethod(HasCompare.class.getMethod("compareTo", String.class)));
+        assertFalse(ObjectMethodsGuru.isCompareToMethod(HasCompareToButDoesNotImplementComparable.class.getDeclaredMethod("compareTo", HasCompareToButDoesNotImplementComparable.class)));
+
+        assertTrue(ObjectMethodsGuru.isCompareToMethod(HasCompare.class.getMethod("compareTo", HasCompare.class)));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/PlatformTest.java b/src/test/java/org/mockito/internal/util/PlatformTest.java
new file mode 100644
index 0000000..05a1cc9
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/PlatformTest.java
@@ -0,0 +1,135 @@
+package org.mockito.internal.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+// Possible description on a IBM J9 VM (see #801)
+//
+// java.specification.version = 1.8
+// java.vm.vendor = IBM Corporation
+// java.vm.version = 2.8
+// java.vm.name = IBM J9 VM
+// java.runtime.version = pwa6480sr1fp10-20150711_01 (SR1 FP10)
+// java.vm.info =
+//   JRE 1.8.0 Windows 7 amd64-64 Compressed References 20150630_255633 (JIT enabled, AOT enabled)
+//   J9VM - R28_jvm.28_20150630_1742_B255633
+//   JIT  - tr.r14.java_20150625_95081.01
+//   GC   - R28_jvm.28_20150630_1742_B255633_CMPRSS
+//   J9CL - 20150630_255633
+// os.name = Windows 7
+// os.version = 6.1
+public class PlatformTest {
+    // TODO use ClassLoaders
+
+    @Test
+    public void const_are_initialized_from_system_properties() {
+        System.out.println(Platform.describe());
+
+        assertThat(Platform.JVM_VERSION).isEqualTo(System.getProperty("java.runtime.version"));
+        assertThat(Platform.JVM_INFO).isEqualTo(System.getProperty("java.vm.info"));
+        assertThat(Platform.JVM_NAME).isEqualTo(System.getProperty("java.vm.name"));
+        assertThat(Platform.JVM_VENDOR).isEqualTo(System.getProperty("java.vm.vendor"));
+        assertThat(Platform.JVM_VENDOR_VERSION).isEqualTo(System.getProperty("java.vm.version"));
+    }
+
+    @Test
+    public void should_warn_for_jvm() throws Exception {
+        assertThat(Platform.warnForVM("Java HotSpot(TM) 64-Bit Server VM",
+                                      "HotSpot", "hotspot warning",
+                                      "IBM", "ibm warning"))
+                .isEqualTo("hotspot warning");
+        assertThat(Platform.warnForVM("IBM J9 VM",
+                                      "HotSpot", "hotspot warning",
+                                      "IBM", "ibm warning"))
+                .isEqualTo("ibm warning");
+        assertThat(Platform.warnForVM("whatever",
+                                      null, "should not be returned",
+                                      null, "should not be returned"))
+                .isEqualTo("");
+    }
+
+    @Test
+    public void should_parse_open_jdk_string_and_report_wether_below_or_nut_update_45() {
+        // Given
+        // Sources :
+        //  - http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
+        //  - http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html
+        //  - http://www.oracle.com/technetwork/java/javase/jdk8-naming-2157130.html
+        //  - http://stackoverflow.com/questions/35844985/how-do-we-get-sr-and-fp-of-ibm-jre-using-java
+        //  - http://www.ibm.com/support/knowledgecenter/SSYKE2_6.0.0/com.ibm.java.doc.user.win32.60/user/java_version_check.html
+        Map<String, Boolean> versions = new HashMap<String, Boolean>() {{
+            put("1.8.0_92-b14", false);
+            put("1.8.0-b24", true);
+            put("1.8.0_5", true);
+            put("1.8.0b5_u44", true);
+            put("1.8.0b5_u92", false);
+            put("1.7.0_4", false);
+            put("1.4.0_03-b04", false);
+            put("1.4.0_03-ea-b01", false);
+            put("pxi3270_27sr4-20160303_03 (SR4)", false);
+            put("pwi3260sr11-20120412_01 (SR11)", false);
+            put("pwa6480sr1fp10-20150711_01 (SR1 FP10)", false);
+            put("null", false);
+        }};
+
+        assertPlatformParsesCorrectlyVariousVersionScheme(versions);
+    }
+
+    @Test
+    public void should_parse_open_jdk9_string() {
+        // The tested method targets Java 8 but should be able to parse other Java version numbers including Java 9
+
+        // Given
+        // Sources :
+        //  - http://openjdk.java.net/jeps/223 (Java 9)
+        //
+        // System Property                 Existing      Proposed
+        // ------------------------------- ------------  --------
+        // Early Access
+        // java.runtime.version            1.9.0-ea-b73  9-ea+73
+        // java.vm.version                 1.9.0-ea-b73  9-ea+73
+        // java.specification.version      1.9           9
+        // java.vm.specification.version   1.9           9
+        //
+        // Major (GA)
+        // java.version                    1.9.0         9
+        // java.runtime.version            1.9.0-b100    9+100
+        // java.vm.version                 1.9.0-b100    9+100
+        // java.specification.version      1.9           9
+        // java.vm.specification.version   1.9           9
+        //
+        // Minor #1 (GA)
+        // java.version                    1.9.0_20      9.1.2
+        // java.runtime.version            1.9.0_20-b62  9.1.2+62
+        // java.vm.version                 1.9.0_20-b62  9.1.2+62
+        // java.specification.version      1.9           9
+        // java.vm.specification.version   1.9           9
+        //
+        // Security #1 (GA)
+        // java.version                    1.9.0_5       9.0.1
+        // java.runtime.version            1.9.0_5-b20   9.0.1+20
+        // java.vm.version                 1.9.0_5-b20   9.0.1+20
+        // java.specification.version      1.9           9
+        // java.vm.specification.version   1.9           9
+        //
+        Map<String, Boolean> versions = new HashMap<String, Boolean>() {{
+            put("9-ea+73", false);
+            put("9+100", false);
+            put("9.1.2+62", false);
+            put("9.0.1+20", false);
+        }};
+
+        assertPlatformParsesCorrectlyVariousVersionScheme(versions);
+    }
+
+
+    private void assertPlatformParsesCorrectlyVariousVersionScheme(Map<String, Boolean> versions) {
+        for (Map.Entry<String, Boolean> version : versions.entrySet()) {
+            assertThat(Platform.isJava8BelowUpdate45(version.getKey())).describedAs(version.getKey())
+                                                                       .isEqualTo(version.getValue());
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/PrimitivesTest.java b/src/test/java/org/mockito/internal/util/PrimitivesTest.java
new file mode 100644
index 0000000..2896bd4
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/PrimitivesTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+
+public class PrimitivesTest {
+    @Test
+    public void should_not_return_null_for_primitives_wrappers() throws Exception {
+        assertNotNull(Primitives.defaultValue(Boolean.class));
+        assertNotNull(Primitives.defaultValue(Character.class));
+        assertNotNull(Primitives.defaultValue(Byte.class));
+        assertNotNull(Primitives.defaultValue(Short.class));
+        assertNotNull(Primitives.defaultValue(Integer.class));
+        assertNotNull(Primitives.defaultValue(Long.class));
+        assertNotNull(Primitives.defaultValue(Float.class));
+        assertNotNull(Primitives.defaultValue(Double.class));
+    }
+
+    @Test
+    public void should_not_return_null_for_primitives() throws Exception {
+        assertNotNull(Primitives.defaultValue(boolean.class));
+        assertNotNull(Primitives.defaultValue(char.class));
+        assertNotNull(Primitives.defaultValue(byte.class));
+        assertNotNull(Primitives.defaultValue(short.class));
+        assertNotNull(Primitives.defaultValue(int.class));
+        assertNotNull(Primitives.defaultValue(long.class));
+        assertNotNull(Primitives.defaultValue(float.class));
+        assertNotNull(Primitives.defaultValue(double.class));
+    }
+
+    @Test
+    public void should_default_values_for_primitive() {
+        assertThat(Primitives.defaultValue(boolean.class)).isFalse();
+        assertThat(Primitives.defaultValue(char.class)).isEqualTo('\u0000');
+        assertThat(Primitives.defaultValue(byte.class)).isEqualTo((byte) 0);
+        assertThat(Primitives.defaultValue(short.class)).isEqualTo((short) 0);
+        assertThat(Primitives.defaultValue(int.class)).isEqualTo(0);
+        assertThat(Primitives.defaultValue(long.class)).isEqualTo(0L);
+        assertThat(Primitives.defaultValue(float.class)).isEqualTo(0.0F);
+        assertThat(Primitives.defaultValue(double.class)).isEqualTo(0.0D);
+    }
+
+    @Test
+    public void should_default_values_for_wrapper() {
+        assertThat(Primitives.defaultValue(Boolean.class)).isFalse();
+        assertThat(Primitives.defaultValue(Character.class)).isEqualTo('\u0000');
+        assertThat(Primitives.defaultValue(Byte.class)).isEqualTo((byte) 0);
+        assertThat(Primitives.defaultValue(Short.class)).isEqualTo((short) 0);
+        assertThat(Primitives.defaultValue(Integer.class)).isEqualTo(0);
+        assertThat(Primitives.defaultValue(Long.class)).isEqualTo(0L);
+        assertThat(Primitives.defaultValue(Float.class)).isEqualTo(0.0F);
+        assertThat(Primitives.defaultValue(Double.class)).isEqualTo(0.0D);
+    }
+
+    @Test
+    public void should_return_null_for_everything_else() throws Exception {
+        assertNull(Primitives.defaultValue(Object.class));
+        assertNull(Primitives.defaultValue(String.class));
+        assertNull(Primitives.defaultValue(null));
+    }
+
+    @Test
+    public void should_check_that_value_type_is_assignable_to_wrapper_reference() {
+        assertThat(Primitives.isAssignableFromWrapper(int.class, Integer.class));
+        assertThat(Primitives.isAssignableFromWrapper(Integer.class, Integer.class));
+        assertThat(Primitives.isAssignableFromWrapper(long.class, Long.class));
+        assertThat(Primitives.isAssignableFromWrapper(Long.class, Long.class));
+        assertThat(Primitives.isAssignableFromWrapper(double.class, Double.class));
+        assertThat(Primitives.isAssignableFromWrapper(Double.class, Double.class));
+        assertThat(Primitives.isAssignableFromWrapper(float.class, Float.class));
+        assertThat(Primitives.isAssignableFromWrapper(Float.class, Float.class));
+        assertThat(Primitives.isAssignableFromWrapper(char.class, Character.class));
+        assertThat(Primitives.isAssignableFromWrapper(Character.class, Character.class));
+        assertThat(Primitives.isAssignableFromWrapper(short.class, Short.class));
+        assertThat(Primitives.isAssignableFromWrapper(Short.class, Short.class));
+        assertThat(Primitives.isAssignableFromWrapper(byte.class, Byte.class));
+        assertThat(Primitives.isAssignableFromWrapper(Byte.class, Byte.class));
+        assertThat(Primitives.isAssignableFromWrapper(boolean.class, Boolean.class));
+        assertThat(Primitives.isAssignableFromWrapper(Boolean.class, Boolean.class));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/SimpleMockitoLogger.java b/src/test/java/org/mockito/internal/util/SimpleMockitoLogger.java
new file mode 100644
index 0000000..129547f
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/SimpleMockitoLogger.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+public class SimpleMockitoLogger implements MockitoLogger {
+
+    private StringBuilder loggedInfo = new StringBuilder();
+
+    public void log(Object what) {
+        loggedInfo.append(what);
+    }
+
+    public String getLoggedInfo() {
+        return loggedInfo.toString();
+    }
+
+    public boolean isEmpty() {
+        return loggedInfo.length() == 0;
+    }
+
+    public SimpleMockitoLogger clear() {
+        loggedInfo = new StringBuilder();
+        return this;
+    }
+
+    public void assertEmpty() {
+        if (loggedInfo.length() != 0) {
+            throw new AssertionError("Expected the logger to be empty but it has:\n" + loggedInfo.toString());
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/SimpleMockitoLoggerTest.java b/src/test/java/org/mockito/internal/util/SimpleMockitoLoggerTest.java
new file mode 100644
index 0000000..2982e49
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/SimpleMockitoLoggerTest.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class SimpleMockitoLoggerTest extends TestBase {
+
+    @Test
+    public void shouldLog() throws Exception {
+        //given
+        SimpleMockitoLogger logger = new SimpleMockitoLogger();
+        //when
+        logger.log("foo");
+        //then
+        assertEquals("foo", logger.getLoggedInfo());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/StringUtilTest.java b/src/test/java/org/mockito/internal/util/StringUtilTest.java
new file mode 100644
index 0000000..14adc6b
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/StringUtilTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class StringUtilTest  {
+
+    @Test
+    public void decamelizeMatcher() throws Exception {
+        assertEquals("<Sentence with strong language>", StringUtil.decamelizeMatcher("SentenceWithStrongLanguage"));
+        assertEquals("<W e i r d o 1>", StringUtil.decamelizeMatcher("WEIRDO1"));
+        assertEquals("<_>", StringUtil.decamelizeMatcher("_"));
+        assertEquals("<Has exactly 3 elements>", StringUtil.decamelizeMatcher("HasExactly3Elements"));
+        assertEquals("<custom argument matcher>", StringUtil.decamelizeMatcher(""));
+    }
+
+    @Test
+    public void join_non() throws Exception {
+        assertThat(StringUtil.join()).isEmpty();;
+    }
+
+    @Test
+    public void join_singleLine() throws Exception {
+        assertThat(StringUtil.join("line1")).hasLineCount(2);
+    }
+
+    @Test
+    public void join_twoLines() throws Exception {
+        assertThat(StringUtil.join("line1","line2")).hasLineCount(3);
+    }
+
+    @Test
+    public void join_hasPreceedingLinebreak() throws Exception {
+        assertThat(StringUtil.join("line1")).isEqualTo("\nline1");
+    }
+
+    @Test
+    public void removeFirstLine() throws Exception {
+        assertThat(StringUtil.removeFirstLine("line1\nline2")).isEqualTo("line2");
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/TimerTest.java b/src/test/java/org/mockito/internal/util/TimerTest.java
new file mode 100644
index 0000000..49cd3c7
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/TimerTest.java
@@ -0,0 +1,50 @@
+package org.mockito.internal.util;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.FriendlyReminderException;
+import org.mockitoutil.TestBase;
+
+public class TimerTest extends TestBase {
+
+    @Test
+    public void should_return_true_if_task_is_in_acceptable_time_bounds() {
+        //given
+        long duration = 10000L;
+        Timer timer = new Timer(duration);
+
+        //when
+        timer.start();
+
+        //then
+        Assertions.assertThat(timer.isCounting()).isTrue();
+    }
+
+    @Test
+    public void should_return_false_when_time_run_out() throws Exception {
+        //given
+        Timer timer = new Timer(0);
+        timer.start();
+
+        //when
+        oneMillisecondPasses();
+
+        //then
+        Assertions.assertThat(timer.isCounting()).isFalse();
+    }
+
+    @Test
+    public void should_throw_friendly_reminder_exception_when_duration_is_negative() {
+        try {
+            new Timer(-1);
+            Assert.fail("It is forbidden to create timer with negative value of timer's duration.");
+        } catch (FriendlyReminderException e) {
+            Assert.assertTrue(true);
+        }
+    }
+
+    private void oneMillisecondPasses() throws InterruptedException {
+        Thread.sleep(1);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSetTest.java b/src/test/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSetTest.java
new file mode 100644
index 0000000..031a654
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSetTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Observer;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class HashCodeAndEqualsSafeSetTest {
+
+    @Rule
+    public MockitoRule r = MockitoJUnit.rule();
+    @Mock
+    private UnmockableHashCodeAndEquals mock1;
+
+    @Test
+    public void can_add_mock_that_have_failing_hashCode_method() throws Exception {
+        new HashCodeAndEqualsSafeSet().add(mock1);
+    }
+
+    @Test
+    public void mock_with_failing_hashCode_method_can_be_added() throws Exception {
+        new HashCodeAndEqualsSafeSet().add(mock1);
+    }
+
+    @Test
+    public void mock_with_failing_equals_method_can_be_used() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = new HashCodeAndEqualsSafeSet();
+        mocks.add(mock1);
+
+        assertThat(mocks.contains(mock1)).isTrue();
+
+        UnmockableHashCodeAndEquals mock2 = mock(UnmockableHashCodeAndEquals.class);
+        assertThat(mocks.contains(mock2)).isFalse();
+    }
+
+    @Test
+    public void can_remove() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = new HashCodeAndEqualsSafeSet();
+        UnmockableHashCodeAndEquals mock = mock1;
+        mocks.add(mock);
+        mocks.remove(mock);
+
+        assertThat(mocks.isEmpty()).isTrue();
+    }
+
+
+    @Test
+    public void can_add_a_collection() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = HashCodeAndEqualsSafeSet.of(
+                mock1,
+                mock(Observer.class));
+
+        HashCodeAndEqualsSafeSet workingSet = new HashCodeAndEqualsSafeSet();
+
+        workingSet.addAll(mocks);
+
+        assertThat(workingSet.containsAll(mocks)).isTrue();
+    }
+
+    @Test
+    public void can_retain_a_collection() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = HashCodeAndEqualsSafeSet.of(
+                mock1,
+                mock(Observer.class));
+
+        HashCodeAndEqualsSafeSet workingSet = new HashCodeAndEqualsSafeSet();
+
+        workingSet.addAll(mocks);
+        workingSet.add(mock(List.class));
+
+        assertThat(workingSet.retainAll(mocks)).isTrue();
+        assertThat(workingSet.containsAll(mocks)).isTrue();
+    }
+
+    @Test
+    public void can_remove_a_collection() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = HashCodeAndEqualsSafeSet.of(
+                mock1,
+                mock(Observer.class));
+
+        HashCodeAndEqualsSafeSet workingSet = new HashCodeAndEqualsSafeSet();
+
+        workingSet.addAll(mocks);
+        workingSet.add(mock(List.class));
+
+        assertThat(workingSet.removeAll(mocks)).isTrue();
+        assertThat(workingSet.containsAll(mocks)).isFalse();
+    }
+
+    @Test
+    public void can_iterate() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = HashCodeAndEqualsSafeSet.of(
+                mock1,
+                mock(Observer.class));
+
+        LinkedList<Object> accumulator = new LinkedList<Object>();
+        for (Object mock : mocks) {
+            accumulator.add(mock);
+        }
+        assertThat(accumulator).isNotEmpty();
+    }
+
+    @Test
+    public void toArray_just_work() throws Exception {
+        HashCodeAndEqualsSafeSet mocks = HashCodeAndEqualsSafeSet.of(mock1);
+
+        assertThat(mocks.toArray()[0]).isSameAs(mock1);
+
+        assertThat(mocks.toArray(new UnmockableHashCodeAndEquals[0])[0]).isSameAs(mock1);
+    }
+
+    @Test(expected=CloneNotSupportedException.class)
+    public void cloneIsNotSupported() throws CloneNotSupportedException{
+        HashCodeAndEqualsSafeSet.of().clone();
+    }
+
+    @Test
+    public void isEmptyAfterClear() throws Exception {
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of(mock1);
+        set.clear();
+
+        assertThat(set).isEmpty();
+    }
+
+    @Test
+    public void isEqualToItself(){
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of(mock1);
+        assertThat(set).isEqualTo(set);
+    }
+
+    @Test
+    public void isNotEqualToAnOtherTypeOfSetWithSameContent(){
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of();
+        assertThat(set).isNotEqualTo(new HashSet<Object>());
+    }
+
+    @Test
+    public void isNotEqualWhenContentIsDifferent(){
+
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of(mock1);
+        assertThat(set).isNotEqualTo(HashCodeAndEqualsSafeSet.of());
+    }
+
+    @Test
+    public void hashCodeIsEqualIfContentIsEqual(){
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of(mock1);
+        assertThat(set.hashCode()).isEqualTo(HashCodeAndEqualsSafeSet.of(mock1).hashCode());
+    }
+
+    @Test
+    public void toStringIsNotNullOrEmpty() throws Exception {
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of(mock1);
+        assertThat(set.toString()).isNotEmpty();
+    }
+
+    @Test
+    public void removeByIterator() throws Exception {
+        HashCodeAndEqualsSafeSet set = HashCodeAndEqualsSafeSet.of(mock1);
+        Iterator<Object> iterator = set.iterator();
+        iterator.next();
+        iterator.remove();
+
+        assertThat(set).isEmpty();
+    }
+
+    private static class UnmockableHashCodeAndEquals {
+        @Override public final int hashCode() {
+            throw new NullPointerException("I'm failing on hashCode and I don't care");
+        }
+
+        @Override public final boolean equals(Object obj) {
+            throw new NullPointerException("I'm failing on equals and I don't care");
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/collections/IdentitySetTest.java b/src/test/java/org/mockito/internal/util/collections/IdentitySetTest.java
new file mode 100644
index 0000000..da62926
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/collections/IdentitySetTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+public class IdentitySetTest {
+
+    IdentitySet set = new IdentitySet();
+
+    @Test
+    public void shouldWork() throws Exception {
+        //when
+        Object o = new Object();
+        set.add(o);
+
+        //then
+        assertTrue(set.contains(o));
+        assertFalse(set.contains(new Object()));
+    }
+
+    class Fake {
+        @Override
+        public boolean equals(Object obj) {
+            return true;
+        }
+    }
+
+    @Test
+    public void shouldWorkEvenIfEqualsTheSame() throws Exception {
+        //given
+        assertEquals(new Fake(), new Fake());
+        Fake fake = new Fake();
+
+        //when
+        set.add(fake);
+
+        //then
+        assertTrue(set.contains(fake));
+        assertFalse(set.contains(new Fake()));
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/util/collections/ListUtilTest.java b/src/test/java/org/mockito/internal/util/collections/ListUtilTest.java
new file mode 100644
index 0000000..58ceafb
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/collections/ListUtilTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util.collections;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.internal.util.collections.ListUtil.Filter;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.assertTrue;
+
+public class ListUtilTest extends TestBase {
+
+    @Test
+    public void shouldFilterList() throws Exception {
+        List<String> list = asList("one", "x", "two", "x", "three");
+        List<String> filtered = ListUtil.filter(list, new Filter<String>() {
+            public boolean isOut(String object) {
+                return object == "x";
+            }
+        });
+
+        Assertions.assertThat(filtered).containsSequence("one", "two", "three");
+    }
+
+    @Test
+    public void shouldReturnEmptyIfEmptyListGiven() throws Exception {
+        List<Object> list = new LinkedList<Object>();
+        List<Object> filtered = ListUtil.filter(list, null);
+        assertTrue(filtered.isEmpty());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/io/IOUtilTest.java b/src/test/java/org/mockito/internal/util/io/IOUtilTest.java
new file mode 100644
index 0000000..4dcdf0c
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/io/IOUtilTest.java
@@ -0,0 +1,33 @@
+package org.mockito.internal.util.io;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+
+public class IOUtilTest {
+
+    @Rule public TemporaryFolder tmp = new TemporaryFolder();
+
+    @Test
+    public void closes_streams() throws Exception {
+        IOUtil.closeQuietly(null);
+        IOUtil.closeQuietly(new ByteArrayOutputStream());
+
+        IOUtil.close(null);
+        IOUtil.close(new ByteArrayOutputStream());
+    }
+
+    @Test
+    public void writes_reads_files() throws Exception {
+        File file = tmp.newFile();
+        IOUtil.writeText("foo\n\nbar", file);
+        assertEquals(asList("foo", "", "bar"), IOUtil.readLines(new FileInputStream(file)));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/AccessibilityChangerTest.java b/src/test/java/org/mockito/internal/util/reflection/AccessibilityChangerTest.java
new file mode 100644
index 0000000..88bf1cf
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/AccessibilityChangerTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.Observable;
+
+import static org.mockitoutil.VmArgAssumptions.assumeVmArgPresent;
+
+public class AccessibilityChangerTest {
+
+    @SuppressWarnings("unused")
+    private Observable whatever;
+
+    @Test
+    public void should_enable_and_safely_disable() throws Exception {
+        AccessibilityChanger changer = new AccessibilityChanger();
+        changer.enableAccess(field("whatever"));
+        changer.safelyDisableAccess(field("whatever"));
+    }
+
+    @Test(expected = java.lang.AssertionError.class)
+    public void safelyDisableAccess_should_fail_when_enableAccess_not_called() throws Exception {
+        assumeVmArgPresent("-ea");
+        new AccessibilityChanger().safelyDisableAccess(field("whatever"));
+    }
+
+
+    private Field field(String fieldName) throws NoSuchFieldException {
+        return this.getClass().getDeclaredField(fieldName);
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/BeanPropertySetterTest.java b/src/test/java/org/mockito/internal/util/reflection/BeanPropertySetterTest.java
new file mode 100644
index 0000000..a0b6119
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/BeanPropertySetterTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.lang.reflect.Field;
+import java.util.UUID;
+
+import static org.junit.Assert.*;
+
+
+public class BeanPropertySetterTest {
+
+    @Test
+    public void use_the_correct_setter_on_the_target() throws Exception {
+        // given
+        SomeBean someBean = new SomeBean();
+        Field theField = someBean.getClass().getDeclaredField("theField");
+        File valueToInject = new File("path");
+
+        // when
+        boolean injected = new BeanPropertySetter(someBean, theField, true).set(valueToInject);
+
+        // then
+        assertTrue(injected);
+        assertTrue(someBean.theFieldSetterWasUsed);
+        assertSame(valueToInject, someBean.getTheField());
+    }
+
+    @Test
+    public void use_the_setter_on_the_target_when_field_name_begins_by_at_least_2_caps() throws Exception {
+        // given
+        BeanWithWeirdFields someBean = new BeanWithWeirdFields();
+        Field theField = someBean.getClass().getDeclaredField("UUID");
+        UUID valueToInject = new UUID(0L, 0L);
+
+        // when
+        boolean injected = new BeanPropertySetter(someBean, theField, true).set(valueToInject);
+
+        // then
+        assertTrue(injected);
+        assertTrue(someBean.theFieldSetterWasUSed);
+        assertSame(valueToInject, someBean.UUID);
+    }
+
+    @Test
+    public void should_not_fail_if_bean_class_declares_only_the_setter_for_the_property() throws Exception {
+        // given
+        SomeBeanWithJustASetter someBean = new SomeBeanWithJustASetter();
+        Field theField = someBean.getClass().getDeclaredField("theField");
+        File valueToInject = new File("path");
+
+        // when
+        boolean injected = new BeanPropertySetter(someBean, theField, true).set(valueToInject);
+
+        // then
+        assertTrue(injected);
+        assertTrue(someBean.theFieldSetterWasUsed);
+    }
+
+    @Test
+    public void should_fail_if_matching_setter_cannot_be_found_and_if_report_failure_is_true() throws Exception {
+        // given
+        SomeBeanWithNoSetterMatchingFieldType bean = new SomeBeanWithNoSetterMatchingFieldType();
+        Field theField = bean.getClass().getDeclaredField("theField");
+        File valueToInject = new File("path");
+
+        try {
+            // when
+            new BeanPropertySetter(bean, theField, true).set(valueToInject);
+            fail();
+        } catch (Exception e) {
+            // then
+            Assertions.assertThat(e.getMessage()).contains("setter not found");
+        }
+    }
+
+    @Test
+    public void return_false_if_no_setter_was_found() throws Exception {
+        // given
+        SomeBeanWithJustAGetter bean = new SomeBeanWithJustAGetter();
+        Field theField = bean.getClass().getDeclaredField("theField");
+        File valueToInject = new File("path");
+
+        // when
+        boolean injected = new BeanPropertySetter(bean, theField).set(valueToInject);
+
+        // then
+        assertFalse(injected);
+    }
+
+    @Test
+    public void return_false_if_no_setter_was_found_and_if_reportNoSetterFound_is_false() throws Exception {
+        // given
+        SomeBeanWithNoSetterMatchingFieldType bean = new SomeBeanWithNoSetterMatchingFieldType();
+        Field theField = bean.getClass().getDeclaredField("theField");
+        File valueToInject = new File("path");
+
+        // when
+        boolean injected = new BeanPropertySetter(bean, theField, false).set(valueToInject);
+
+        // then
+        assertFalse(injected);
+    }
+
+    static class SomeBean {
+        private File theField;
+        boolean theFieldSetterWasUsed;
+
+        public void setTheField(final File theField) {
+            theFieldSetterWasUsed = true;
+            this.theField = theField;
+        }
+
+        public File getTheField() {
+            return theField;
+        }
+    }
+
+    static class SomeBeanWithJustASetter {
+        private File theField;
+        boolean theFieldSetterWasUsed;
+
+        public void setTheField(final File theField) {
+            theFieldSetterWasUsed = true;
+            this.theField = theField;
+        }
+    }
+    static class SomeBeanWithJustAGetter {
+        private File theField;
+
+        public File getTheField() {
+            return theField;
+        }
+    }
+
+    static class SomeBeanWithNoSetterMatchingFieldType {
+        private File theField;
+        boolean theFieldSetterWasUsed;
+
+        public void setTheField(final FileOutputStream somethingElse) {
+            theFieldSetterWasUsed = true;
+        }
+    }
+
+    static class BeanWithWeirdFields {
+        private UUID UUID;
+        boolean theFieldSetterWasUSed;
+
+        public void setUUID(UUID UUID) {
+            theFieldSetterWasUSed = true;
+            this.UUID = UUID;
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/DummyClassForTests.java b/src/test/java/org/mockito/internal/util/reflection/DummyClassForTests.java
new file mode 100644
index 0000000..17d71ad
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/DummyClassForTests.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+public class DummyClassForTests extends DummyParentClassForTests {
+
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/DummyParentClassForTests.java b/src/test/java/org/mockito/internal/util/reflection/DummyParentClassForTests.java
new file mode 100644
index 0000000..6967c02
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/DummyParentClassForTests.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+public class DummyParentClassForTests {
+
+    @SuppressWarnings("unused")//I know, I know. We're doing nasty reflection hacks here...
+    private String somePrivateField;
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/FieldInitializerTest.java b/src/test/java/org/mockito/internal/util/reflection/FieldInitializerTest.java
new file mode 100644
index 0000000..0b8141e
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/FieldInitializerTest.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.reflection.FieldInitializer.ConstructorArgumentResolver;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+
+
+
+public class FieldInitializerTest {
+
+    private StaticClass alreadyInstantiated = new StaticClass();
+    private StaticClass noConstructor;
+    private StaticClassWithDefaultConstructor defaultConstructor;
+    private StaticClassWithPrivateDefaultConstructor privateDefaultConstructor;
+    private StaticClassWithoutDefaultConstructor noDefaultConstructor;
+    private StaticClassThrowingExceptionDefaultConstructor throwingExDefaultConstructor;
+    private AbstractStaticClass abstractType;
+    private Interface interfaceType;
+    private InnerClassType innerClassType;
+    private AbstractStaticClass instantiatedAbstractType = new ConcreteStaticClass();
+    private Interface instantiatedInterfaceType =  new ConcreteStaticClass();
+    private InnerClassType instantiatedInnerClassType = new InnerClassType();
+
+    @Test
+    public void should_keep_same_instance_if_field_initialized() throws Exception {
+        final StaticClass backupInstance = alreadyInstantiated;
+        FieldInitializer fieldInitializer = new FieldInitializer(this, field("alreadyInstantiated"));
+        FieldInitializationReport report = fieldInitializer.initialize();
+
+        assertSame(backupInstance, report.fieldInstance());
+        assertFalse(report.fieldWasInitialized());
+        assertFalse(report.fieldWasInitializedUsingContructorArgs());
+    }
+
+    @Test
+    public void should_instantiate_field_when_type_has_no_constructor() throws Exception {
+        FieldInitializer fieldInitializer = new FieldInitializer(this, field("noConstructor"));
+        FieldInitializationReport report = fieldInitializer.initialize();
+
+        assertNotNull(report.fieldInstance());
+        assertTrue(report.fieldWasInitialized());
+        assertFalse(report.fieldWasInitializedUsingContructorArgs());
+    }
+
+    @Test
+    public void should_instantiate_field_with_default_constructor() throws Exception {
+        FieldInitializer fieldInitializer = new FieldInitializer(this, field("defaultConstructor"));
+        FieldInitializationReport report = fieldInitializer.initialize();
+
+        assertNotNull(report.fieldInstance());
+        assertTrue(report.fieldWasInitialized());
+        assertFalse(report.fieldWasInitializedUsingContructorArgs());
+    }
+
+    @Test
+    public void should_instantiate_field_with_private_default_constructor() throws Exception {
+        FieldInitializer fieldInitializer = new FieldInitializer(this, field("privateDefaultConstructor"));
+        FieldInitializationReport report = fieldInitializer.initialize();
+
+        assertNotNull(report.fieldInstance());
+        assertTrue(report.fieldWasInitialized());
+        assertFalse(report.fieldWasInitializedUsingContructorArgs());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_to_instantiate_field_if_no_default_constructor() throws Exception {
+        FieldInitializer fieldInitializer = new FieldInitializer(this, field("noDefaultConstructor"));
+        fieldInitializer.initialize();
+    }
+
+    @Test
+    public void should_fail_to_instantiate_field_if_default_constructor_throws_exception() throws Exception {
+        FieldInitializer fieldInitializer = new FieldInitializer(this, field("throwingExDefaultConstructor"));
+        try {
+            fieldInitializer.initialize();
+            fail();
+        } catch (MockitoException e) {
+            InvocationTargetException ite = (InvocationTargetException) e.getCause();
+            assertTrue(ite.getTargetException() instanceof NullPointerException);
+            assertEquals("business logic failed", ite.getTargetException().getMessage());
+        }
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_for_abstract_field() throws Exception {
+        new FieldInitializer(this, field("abstractType"));
+    }
+
+    @Test
+    public void should_not_fail_if_abstract_field_is_instantiated() throws Exception {
+        new FieldInitializer(this, field("instantiatedAbstractType"));
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_for_interface_field() throws Exception {
+        new FieldInitializer(this, field("interfaceType"));
+    }
+
+    @Test
+    public void should_not_fail_if_interface_field_is_instantiated() throws Exception {
+        new FieldInitializer(this, field("instantiatedInterfaceType"));
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_for_local_type_field() throws Exception {
+        // when
+        class LocalType { }
+
+        class TheTestWithLocalType {
+            @InjectMocks LocalType field;
+        }
+
+        TheTestWithLocalType testWithLocalType = new TheTestWithLocalType();
+
+        // when
+        new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field"));
+    }
+
+    @Test
+    public void should_not_fail_if_local_type_field_is_instantiated() throws Exception {
+        // when
+        class LocalType { }
+
+        class TheTestWithLocalType {
+            @InjectMocks LocalType field = new LocalType();
+        }
+
+        TheTestWithLocalType testWithLocalType = new TheTestWithLocalType();
+
+        // when
+        new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field"));
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_fail_for_inner_class_field() throws Exception {
+        new FieldInitializer(this, field("innerClassType"));
+    }
+
+    @Test
+    public void should_not_fail_if_inner_class_field_is_instantiated() throws Exception {
+        new FieldInitializer(this, field("instantiatedInnerClassType"));
+    }
+
+    @Test
+    public void can_instantiate_class_with_parameterized_constructor() throws Exception {
+        ConstructorArgumentResolver resolver = given(mock(ConstructorArgumentResolver.class).resolveTypeInstances(any(Class.class)))
+                        .willReturn(new Object[]{null}).getMock();
+
+        new FieldInitializer(this, field("noDefaultConstructor"), resolver).initialize();
+
+        assertNotNull(noDefaultConstructor);
+    }
+
+    private Field field(String fieldName) throws NoSuchFieldException {
+        return this.getClass().getDeclaredField(fieldName);
+    }
+
+    static class StaticClass {
+    }
+
+    static class StaticClassWithDefaultConstructor {
+        StaticClassWithDefaultConstructor() { }
+    }
+
+    static class StaticClassWithPrivateDefaultConstructor {
+        private StaticClassWithPrivateDefaultConstructor() { }
+    }
+
+    static class StaticClassWithoutDefaultConstructor {
+        private StaticClassWithoutDefaultConstructor(String param) { }
+    }
+
+    static class StaticClassThrowingExceptionDefaultConstructor {
+        StaticClassThrowingExceptionDefaultConstructor() throws Exception {
+            throw new NullPointerException("business logic failed");
+        }
+    }
+
+    static abstract class AbstractStaticClass {
+        public AbstractStaticClass() {}
+    }
+
+    interface Interface {
+
+    }
+
+    static class ConcreteStaticClass extends AbstractStaticClass implements Interface {
+    }
+
+    class InnerClassType {
+        InnerClassType() { }
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/FieldReaderTest.java b/src/test/java/org/mockito/internal/util/reflection/FieldReaderTest.java
new file mode 100644
index 0000000..a46b0c1
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/FieldReaderTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+@SuppressWarnings("unused")
+public class FieldReaderTest extends TestBase {
+
+    class Foo {
+        private final String isNull = null;
+        private final String notNull = "";
+    }
+
+    @Test
+    public void shouldKnowWhenNull() throws Exception {
+        //when
+        FieldReader reader = new FieldReader(new Foo(), Foo.class.getDeclaredField("isNull"));
+        //then
+        assertTrue(reader.isNull());
+    }
+
+    @Test
+    public void shouldKnowWhenNotNull() throws Exception {
+        //when
+        FieldReader reader = new FieldReader(new Foo(), Foo.class.getDeclaredField("notNull"));
+        //then
+        assertFalse(reader.isNull());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/FieldsTest.java b/src/test/java/org/mockito/internal/util/reflection/FieldsTest.java
new file mode 100644
index 0000000..d86fb30
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/FieldsTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.util.reflection.Fields.syntheticField;
+
+public class FieldsTest {
+
+    @Test
+    public void fields_should_return_all_declared_fields_in_hierarchy() throws Exception {
+        assertThat(Fields.allDeclaredFieldsOf(new HierarchyOfClasses()).filter(syntheticField()).names())
+                .containsOnly("a", "b", "static_a", "static_b");
+    }
+
+    @Test
+    public void fields_should_return_declared_fields() throws Exception {
+        assertThat(Fields.declaredFieldsOf(new HierarchyOfClasses()).filter(syntheticField()).names())
+                .containsOnly("b", "static_b");
+    }
+
+    @Test
+    public void can_filter_not_null_fields() throws Exception {
+        assertThat(Fields.declaredFieldsOf(new NullOrNotNullFields()).notNull().filter(syntheticField()).names())
+                .containsOnly("c");
+    }
+
+    @Test
+    public void can_get_values_of_instance_fields() throws Exception {
+        assertThat(Fields.declaredFieldsOf(new ValuedFields()).filter(syntheticField()).assignedValues())
+                .containsOnly("a", "b");
+    }
+
+
+    @Test
+    public void can_get_list_of_InstanceField() throws Exception {
+        ValuedFields instance = new ValuedFields();
+
+        assertThat(Fields.declaredFieldsOf(instance).filter(syntheticField()).instanceFields())
+                .containsOnly(new InstanceField(field("a", instance), instance),
+                              new InstanceField(field("b", instance), instance)
+                );
+    }
+
+    private Field field(String name, Object instance) throws NoSuchFieldException {
+        return instance.getClass().getDeclaredField(name);
+    }
+
+
+    interface AnInterface {
+        int someStaticInInterface = 0;
+
+    }
+    public static class ParentClass implements AnInterface {
+        static int static_a;
+        int a;
+
+    }
+    public static class HierarchyOfClasses extends ParentClass {
+        static int static_b;
+        int b = 1;
+
+    }
+    public static class NullOrNotNullFields {
+        static Object static_b;
+        Object b;
+        Object c = new Object();
+    }
+
+    public static class ValuedFields {
+        String a = "a";
+        String b = "b";
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/GenericArrayReturnTypeTest.java b/src/test/java/org/mockito/internal/util/reflection/GenericArrayReturnTypeTest.java
new file mode 100644
index 0000000..ee5ee30
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/GenericArrayReturnTypeTest.java
@@ -0,0 +1,36 @@
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+import org.mockito.Answers;
+
+import java.util.Set;
+
+import static org.mockito.Mockito.mock;
+
+public class GenericArrayReturnTypeTest {
+
+    @Test
+    public void toArrayTypedDoesNotWork() throws Exception {
+        Container container = mock(Container.class, Answers.RETURNS_DEEP_STUBS);
+        container.getInnerContainer().getTheProblem().toArray(new String[]{});
+    }
+
+    class Container {
+
+        private InnerContainer innerContainer;
+
+        public InnerContainer getInnerContainer() {
+            return innerContainer;
+        }
+    }
+
+    class InnerContainer {
+
+        private Set<String> theProblem;
+
+        public Set<String> getTheProblem() {
+            return theProblem;
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/GenericMasterTest.java b/src/test/java/org/mockito/internal/util/reflection/GenericMasterTest.java
new file mode 100644
index 0000000..4125e09
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/GenericMasterTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.*;
+
+import static org.junit.Assert.assertEquals;
+
+public class GenericMasterTest {
+
+    GenericMaster m = new GenericMaster();
+
+    List<String> one;
+    Set<Integer> two;
+    Map<Double, String> map;
+    String nonGeneric;
+    List<Set<String>> nested;
+    List<Set<Collection<String>>> multiNested;
+
+    public interface ListSet extends List<Set<?>> {}
+    public interface MapNumberString extends Map<Number, String> {}
+    public class HashMapNumberString<K extends Number> extends HashMap<K, String> {}
+
+    public List<Number> numberList() { return null; }
+    public Comparable<Number> numberComparable() { return null; }
+    @SuppressWarnings("rawtypes")
+    public List rawList() { return null; }
+    public List<? extends Type> typeList() { return null; }
+
+
+
+    @Test
+    public void should_find_generic_class() throws Exception {
+        assertEquals(String.class, m.getGenericType(field("one")));
+        assertEquals(Integer.class, m.getGenericType(field("two")));
+        assertEquals(Double.class, m.getGenericType(field("map")));
+    }
+
+    @Test
+    public void should_get_object_for_non_generic() throws Exception {
+        assertEquals(Object.class, m.getGenericType(field("nonGeneric")));
+    }
+
+    @Test
+    public void should_deal_with_nested_generics() throws Exception {
+        assertEquals(Set.class, m.getGenericType(field("nested")));
+        assertEquals(Set.class, m.getGenericType(field("multiNested")));
+    }
+
+    private Field field(String fieldName) throws SecurityException, NoSuchFieldException {
+        return this.getClass().getDeclaredField(fieldName);
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/GenericMetadataSupportTest.java b/src/test/java/org/mockito/internal/util/reflection/GenericMetadataSupportTest.java
new file mode 100644
index 0000000..323efbf
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/GenericMetadataSupportTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.internal.util.reflection.GenericMetadataSupport.inferFrom;
+
+public class GenericMetadataSupportTest {
+
+    interface GenericsSelfReference<T extends GenericsSelfReference<T>> {
+        T self();
+    }
+    interface UpperBoundedTypeWithClass<E extends Number & Comparable<E>> {
+        E get();
+    }
+    interface UpperBoundedTypeWithInterfaces<E extends Comparable<E> & Cloneable> {
+        E get();
+    }
+    interface ListOfNumbers extends List<Number> {}
+    interface AnotherListOfNumbers extends ListOfNumbers {}
+
+    abstract class ListOfNumbersImpl implements ListOfNumbers {}
+    abstract class AnotherListOfNumbersImpl extends ListOfNumbersImpl {}
+
+    interface ListOfAnyNumbers<N extends Number & Cloneable> extends List<N> {}
+
+    interface GenericsNest<K extends Comparable<K> & Cloneable> extends Map<K, Set<Number>> {
+        Set<Number> remove(Object key); // override with fixed ParameterizedType
+        List<? super Integer> returning_wildcard_with_class_lower_bound();
+        List<? super K> returning_wildcard_with_typeVar_lower_bound();
+        List<? extends K> returning_wildcard_with_typeVar_upper_bound();
+        K returningK();
+        <O extends K> List<O> paramType_with_type_params();
+        <S, T extends S> T two_type_params();
+        <O extends K> O typeVar_with_type_params();
+    }
+
+    static class StringList extends ArrayList<String> { }
+
+    @Test
+    public void typeVariable_of_self_type() {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsSelfReference.class).resolveGenericReturnType(firstNamedMethod("self", GenericsSelfReference.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(GenericsSelfReference.class);
+    }
+
+    @Test
+    public void can_get_raw_type_from_Class() throws Exception {
+        assertThat(inferFrom(ListOfAnyNumbers.class).rawType()).isEqualTo(ListOfAnyNumbers.class);
+        assertThat(inferFrom(ListOfNumbers.class).rawType()).isEqualTo(ListOfNumbers.class);
+        assertThat(inferFrom(GenericsNest.class).rawType()).isEqualTo(GenericsNest.class);
+        assertThat(inferFrom(StringList.class).rawType()).isEqualTo(StringList.class);
+    }
+
+    @Test
+    public void can_get_raw_type_from_ParameterizedType() throws Exception {
+        assertThat(inferFrom(ListOfAnyNumbers.class.getGenericInterfaces()[0]).rawType()).isEqualTo(List.class);
+        assertThat(inferFrom(ListOfNumbers.class.getGenericInterfaces()[0]).rawType()).isEqualTo(List.class);
+        assertThat(inferFrom(GenericsNest.class.getGenericInterfaces()[0]).rawType()).isEqualTo(Map.class);
+        assertThat(inferFrom(StringList.class.getGenericSuperclass()).rawType()).isEqualTo(ArrayList.class);
+    }
+
+    @Test
+    public void can_get_type_variables_from_Class() throws Exception {
+        assertThat(inferFrom(GenericsNest.class).actualTypeArguments().keySet()).hasSize(1).extracting("name").contains("K");
+        assertThat(inferFrom(ListOfNumbers.class).actualTypeArguments().keySet()).isEmpty();
+        assertThat(inferFrom(ListOfAnyNumbers.class).actualTypeArguments().keySet()).hasSize(1).extracting("name").contains("N");
+        assertThat(inferFrom(Map.class).actualTypeArguments().keySet()).hasSize(2).extracting("name").contains("K", "V");
+        assertThat(inferFrom(Serializable.class).actualTypeArguments().keySet()).isEmpty();
+        assertThat(inferFrom(StringList.class).actualTypeArguments().keySet()).isEmpty();
+    }
+
+    @Test
+    public void can_resolve_type_variables_from_ancestors() throws Exception {
+        Method listGet = List.class.getMethod("get", int.class);
+        assertThat(inferFrom(AnotherListOfNumbers.class).resolveGenericReturnType(listGet).rawType()).isEqualTo(Number.class);
+        assertThat(inferFrom(AnotherListOfNumbersImpl.class).resolveGenericReturnType(listGet).rawType()).isEqualTo(Number.class);
+    }
+
+    @Test
+    public void can_get_type_variables_from_ParameterizedType() throws Exception {
+        assertThat(inferFrom(GenericsNest.class.getGenericInterfaces()[0]).actualTypeArguments().keySet()).hasSize(2).extracting("name").contains("K", "V");
+        assertThat(inferFrom(ListOfAnyNumbers.class.getGenericInterfaces()[0]).actualTypeArguments().keySet()).hasSize(1).extracting("name").contains("E");
+        assertThat(inferFrom(Integer.class.getGenericInterfaces()[0]).actualTypeArguments().keySet()).hasSize(1).extracting("name").contains("T");
+        assertThat(inferFrom(StringBuilder.class.getGenericInterfaces()[0]).actualTypeArguments().keySet()).isEmpty();
+        assertThat(inferFrom(StringList.class).actualTypeArguments().keySet()).isEmpty();
+    }
+
+    @Test
+    public void typeVariable_return_type_of____iterator____resolved_to_Iterator_and_type_argument_to_String() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(StringList.class).resolveGenericReturnType(firstNamedMethod("iterator", StringList.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(Iterator.class);
+        assertThat(genericMetadata.actualTypeArguments().values()).contains(String.class);
+    }
+
+    @Test
+    public void typeVariable_return_type_of____get____resolved_to_Set_and_type_argument_to_Number() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("get", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(Set.class);
+        assertThat(genericMetadata.actualTypeArguments().values()).contains(Number.class);
+    }
+
+    @Test
+    public void bounded_typeVariable_return_type_of____returningK____resolved_to_Comparable_and_with_BoundedType() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("returningK", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(Comparable.class);
+        GenericMetadataSupport extraInterface_0 = inferFrom(genericMetadata.extraInterfaces().get(0));
+        assertThat(extraInterface_0.rawType()).isEqualTo(Cloneable.class);
+    }
+
+    @Test
+    public void fixed_ParamType_return_type_of____remove____resolved_to_Set_and_type_argument_to_Number() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("remove", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(Set.class);
+        assertThat(genericMetadata.actualTypeArguments().values()).contains(Number.class);
+    }
+
+    @Test
+    public void paramType_return_type_of____values____resolved_to_Collection_and_type_argument_to_Parameterized_Set() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("values", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(Collection.class);
+        GenericMetadataSupport fromTypeVariableE = inferFrom(typeVariableValue(genericMetadata.actualTypeArguments(), "E"));
+        assertThat(fromTypeVariableE.rawType()).isEqualTo(Set.class);
+        assertThat(fromTypeVariableE.actualTypeArguments().values()).contains(Number.class);
+    }
+
+    @Test
+    public void paramType_with_type_parameters_return_type_of____paramType_with_type_params____resolved_to_Collection_and_type_argument_to_Parameterized_Set() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("paramType_with_type_params", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(List.class);
+        Type firstBoundOfE = ((GenericMetadataSupport.TypeVarBoundedType) typeVariableValue(genericMetadata.actualTypeArguments(), "E")).firstBound();
+        assertThat(inferFrom(firstBoundOfE).rawType()).isEqualTo(Comparable.class);
+    }
+
+    @Test
+    public void typeVariable_with_type_parameters_return_type_of____typeVar_with_type_params____resolved_K_hence_to_Comparable_and_with_BoundedType() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("typeVar_with_type_params", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(Comparable.class);
+        GenericMetadataSupport extraInterface_0 = inferFrom(genericMetadata.extraInterfaces().get(0));
+        assertThat(extraInterface_0.rawType()).isEqualTo(Cloneable.class);
+    }
+
+    @Test
+    public void class_return_type_of____append____resolved_to_StringBuilder_and_type_arguments() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(StringBuilder.class).resolveGenericReturnType(firstNamedMethod("append", StringBuilder.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(StringBuilder.class);
+        assertThat(genericMetadata.actualTypeArguments()).isEmpty();
+    }
+
+
+
+    @Test
+    public void paramType_with_wildcard_return_type_of____returning_wildcard_with_class_lower_bound____resolved_to_List_and_type_argument_to_Integer() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("returning_wildcard_with_class_lower_bound", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(List.class);
+        GenericMetadataSupport.BoundedType boundedType = (GenericMetadataSupport.BoundedType) typeVariableValue(genericMetadata.actualTypeArguments(), "E");
+        assertThat(boundedType.firstBound()).isEqualTo(Integer.class);
+        assertThat(boundedType.interfaceBounds()).isEmpty();
+    }
+
+    @Test
+    public void paramType_with_wildcard_return_type_of____returning_wildcard_with_typeVar_lower_bound____resolved_to_List_and_type_argument_to_Integer() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("returning_wildcard_with_typeVar_lower_bound", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(List.class);
+        GenericMetadataSupport.BoundedType boundedType = (GenericMetadataSupport.BoundedType) typeVariableValue(genericMetadata.actualTypeArguments(), "E");
+
+        assertThat(inferFrom(boundedType.firstBound()).rawType()).isEqualTo(Comparable.class);
+        assertThat(boundedType.interfaceBounds()).contains(Cloneable.class);    }
+
+    @Test
+    public void paramType_with_wildcard_return_type_of____returning_wildcard_with_typeVar_upper_bound____resolved_to_List_and_type_argument_to_Integer() throws Exception {
+        GenericMetadataSupport genericMetadata = inferFrom(GenericsNest.class).resolveGenericReturnType(firstNamedMethod("returning_wildcard_with_typeVar_upper_bound", GenericsNest.class));
+
+        assertThat(genericMetadata.rawType()).isEqualTo(List.class);
+        GenericMetadataSupport.BoundedType boundedType = (GenericMetadataSupport.BoundedType) typeVariableValue(genericMetadata.actualTypeArguments(), "E");
+
+        assertThat(inferFrom(boundedType.firstBound()).rawType()).isEqualTo(Comparable.class);
+        assertThat(boundedType.interfaceBounds()).contains(Cloneable.class);
+    }
+
+    private Type typeVariableValue(Map<TypeVariable<?>, Type> typeVariables, String typeVariableName) {
+        for (Map.Entry<TypeVariable<?>, Type> typeVariableTypeEntry : typeVariables.entrySet()) {
+            if (typeVariableTypeEntry.getKey().getName().equals(typeVariableName)) {
+                return typeVariableTypeEntry.getValue();
+            }
+        }
+
+        fail("'" + typeVariableName + "' was not found in " + typeVariables);
+        return null; // unreachable
+    }
+
+    private Method firstNamedMethod(String methodName, Class<?> clazz) {
+        for (Method method : clazz.getMethods()) {
+            boolean protect_against_different_jdk_ordering_avoiding_bridge_methods = !method.isBridge();
+            if (method.getName().contains(methodName) && protect_against_different_jdk_ordering_avoiding_bridge_methods) {
+                return method;
+            }
+        }
+        throw new IllegalStateException("The method : '" + methodName + "' do not exist in '" + clazz.getSimpleName() + "'");
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/GenericTypeExtractorTest.java b/src/test/java/org/mockito/internal/util/reflection/GenericTypeExtractorTest.java
new file mode 100644
index 0000000..06bac5a
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/GenericTypeExtractorTest.java
@@ -0,0 +1,64 @@
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.internal.util.reflection.GenericTypeExtractor.genericTypeOf;
+
+public class GenericTypeExtractorTest extends TestBase {
+
+    class Base<T> {}
+    static class StaticBase<T> {}
+    interface IBase<T> {}
+    interface StaticIBase<T> {}
+
+    class IntImpl extends Base<Integer> {}
+    static class StaticIntImpl extends StaticBase<Integer> {}
+    class NestedImpl extends Base<Base<String>> {}
+    class NonGeneric extends Base {}
+
+    class IIntImpl implements IBase<Integer>{}
+    class INestedImpl implements IBase<IBase<String>>{}
+    class INonGeneric implements IBase {}
+    class Mixed extends Base<Integer> implements IBase<String> {}
+
+    class Deeper extends IntImpl implements Serializable {}
+    class EvenDeeper extends Deeper implements Cloneable {}
+    interface Iface extends IBase<Integer> {}
+    interface IDeeper extends Serializable, Iface, Cloneable {}
+
+    interface Crazy extends Serializable, IDeeper, Cloneable {}
+    class Crazier extends EvenDeeper implements Crazy {}
+
+    @Test public void finds_generic_type() {
+        assertEquals(Integer.class, genericTypeOf(IntImpl.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(StaticIntImpl.class, StaticBase.class, IBase.class));
+
+        assertEquals(Object.class, genericTypeOf(NestedImpl.class, Base.class, IBase.class));
+        assertEquals(Object.class, genericTypeOf(NonGeneric.class, Base.class, IBase.class));
+        assertEquals(Object.class, genericTypeOf(String.class, Base.class, IBase.class));
+        assertEquals(Object.class, genericTypeOf(String.class, List.class, Map.class));
+
+        assertEquals(String.class, genericTypeOf(new Base<String>() {}.getClass(), Base.class, IBase.class));
+        assertEquals(String.class, genericTypeOf(new IBase<String>() {}.getClass(), Base.class, IBase.class));
+        assertEquals(String.class, genericTypeOf(new StaticBase<String>() {}.getClass(), StaticBase.class, IBase.class));
+        assertEquals(String.class, genericTypeOf(new StaticIBase<String>() {}.getClass(), Base.class, StaticIBase.class));
+
+        assertEquals(Integer.class, genericTypeOf(Mixed.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(IIntImpl.class, Base.class, IBase.class));
+        assertEquals(Object.class, genericTypeOf(INestedImpl.class, Base.class, IBase.class));
+        assertEquals(Object.class, genericTypeOf(INonGeneric.class, IBase.class, INonGeneric.class));
+
+        assertEquals(Integer.class, genericTypeOf(Deeper.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(EvenDeeper.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(Iface.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(IDeeper.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(Crazy.class, Base.class, IBase.class));
+        assertEquals(Integer.class, genericTypeOf(Crazier.class, Base.class, IBase.class));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/LenientCopyToolTest.java b/src/test/java/org/mockito/internal/util/reflection/LenientCopyToolTest.java
new file mode 100644
index 0000000..c27e92f
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/LenientCopyToolTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.Field;
+import java.util.LinkedList;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class LenientCopyToolTest extends TestBase {
+
+    private LenientCopyTool tool = new LenientCopyTool();
+
+    static class InheritMe {
+        protected String protectedInherited = "protected";
+        private String privateInherited = "private";
+    }
+
+    public static class SomeObject extends InheritMe {
+        @SuppressWarnings("unused")
+        // required because static fields needs to be excluded from copying
+        private static int staticField = -100;
+        private int privateField = -100;
+        private transient int privateTransientField = -100;
+        String defaultField = "-100";
+        protected Object protectedField = new Object();
+        public SomeOtherObject instancePublicField = new SomeOtherObject();
+        final int finalField;
+
+        public SomeObject(int finalField) {
+            this.finalField = finalField;
+        }
+    }
+
+    public static class SomeOtherObject {
+    }
+
+    private SomeObject from = new SomeObject(100);
+    private SomeObject to = mock(SomeObject.class);
+
+    @Test
+    public void shouldShallowCopyBasicFinalField() throws Exception {
+        // given
+        assertEquals(100, from.finalField);
+        assertThat(to.finalField).isNotEqualTo(100);
+
+        // when
+        tool.copyToMock(from, to);
+
+        // then
+        assertEquals(100, to.finalField);
+    }
+
+    @Test
+    public void shouldShallowCopyTransientPrivateFields() throws Exception {
+        // given
+        from.privateTransientField = 1000;
+        assertThat(to.privateTransientField).isNotEqualTo(1000);
+
+        // when
+        tool.copyToMock(from, to);
+
+        // then
+        assertEquals(1000, to.privateTransientField);
+    }
+
+    @Test
+    public void shouldShallowCopyLinkedListIntoMock() throws Exception {
+        // given
+        LinkedList fromList = new LinkedList();
+        LinkedList toList = mock(LinkedList.class);
+
+        // when
+        tool.copyToMock(fromList, toList);
+
+        // then no exception is thrown
+    }
+
+    @Test
+    public void shouldShallowCopyFieldValuesIntoMock() throws Exception {
+        // given
+        from.defaultField = "foo";
+        from.instancePublicField = new SomeOtherObject();
+        from.privateField = 1;
+        from.privateTransientField = 2;
+        from.protectedField = 3;
+
+        assertThat(to.defaultField).isNotEqualTo(from.defaultField);
+        assertThat(to.instancePublicField).isNotEqualTo(from.instancePublicField);
+        assertThat(to.privateField).isNotEqualTo(from.privateField);
+        assertThat(to.privateTransientField).isNotEqualTo(from.privateTransientField);
+        assertThat(to.protectedField).isNotEqualTo(from.protectedField);
+
+        // when
+        tool.copyToMock(from, to);
+
+        // then
+        assertEquals(from.defaultField, to.defaultField);
+        assertEquals(from.instancePublicField, to.instancePublicField);
+        assertEquals(from.privateField, to.privateField);
+        assertEquals(from.privateTransientField, to.privateTransientField);
+        assertEquals(from.protectedField, to.protectedField);
+    }
+
+    @Test
+    public void shouldCopyValuesOfInheritedFields() throws Exception {
+        //given
+        ((InheritMe) from).privateInherited = "foo";
+        ((InheritMe) from).protectedInherited = "bar";
+
+        assertThat(((InheritMe) to).privateInherited).isNotEqualTo(((InheritMe) from).privateInherited);
+
+        //when
+        tool.copyToMock(from, to);
+
+        //then
+        assertEquals(((InheritMe) from).privateInherited, ((InheritMe) to).privateInherited);
+    }
+
+    @Test
+    public void shouldEnableAndThenDisableAccessibility() throws Exception {
+        //given
+        Field privateField = SomeObject.class.getDeclaredField("privateField");
+        assertFalse(privateField.isAccessible());
+
+        //when
+        tool.copyToMock(from, to);
+
+        //then
+        privateField = SomeObject.class.getDeclaredField("privateField");
+        assertFalse(privateField.isAccessible());
+    }
+
+    @Test
+    public void shouldContinueEvenIfThereAreProblemsCopyingSingleFieldValue() throws Exception {
+        //given
+        tool.fieldCopier = mock(FieldCopier.class);
+
+        doNothing().
+        doThrow(new IllegalAccessException()).
+        doNothing().
+        when(tool.fieldCopier).
+        copyValue(anyObject(), anyObject(), any(Field.class));
+
+        //when
+        tool.copyToMock(from, to);
+
+        //then
+        verify(tool.fieldCopier, atLeast(3)).copyValue(any(), any(), any(Field.class));
+    }
+
+    @Test
+    public void shouldBeAbleToCopyFromRealObjectToRealObject() throws Exception {
+
+        // given
+        from.defaultField = "defaultField";
+        from.instancePublicField = new SomeOtherObject();
+        from.privateField = 1;
+        from.privateTransientField = 2;
+        from.protectedField = "protectedField";
+        from.protectedInherited = "protectedInherited";
+        to = new SomeObject(0);
+
+        // when
+        tool.copyToRealObject(from, to);
+
+        // then
+        assertEquals(from.defaultField, to.defaultField);
+        assertEquals(from.instancePublicField, to.instancePublicField);
+        assertEquals(from.privateField, to.privateField);
+        assertEquals(from.privateTransientField, to.privateTransientField);
+        assertEquals(from.protectedField, to.protectedField);
+        assertEquals(from.protectedInherited, to.protectedInherited);
+
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/ParameterizedConstructorInstantiatorTest.java b/src/test/java/org/mockito/internal/util/reflection/ParameterizedConstructorInstantiatorTest.java
new file mode 100644
index 0000000..6f3677a
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/ParameterizedConstructorInstantiatorTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util.reflection;
+
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.reflection.FieldInitializer.ConstructorArgumentResolver;
+import org.mockito.internal.util.reflection.FieldInitializer.ParameterizedConstructorInstantiator;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.Observer;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+
+@SuppressWarnings("unchecked")
+@RunWith(MockitoJUnitRunner.class)
+public class ParameterizedConstructorInstantiatorTest {
+
+    private Set<?> whateverForNow;
+    private OneConstructor withOneConstructor;
+    private MultipleConstructor withMultipleConstructor;
+    private NoArgConstructor withNoArgConstructor;
+    private ThrowingConstructor withThrowingConstructor;
+    private VarargConstructor withVarargConstructor;
+
+    @After
+    public void ensure_instances_to_create_are_null() {
+        withMultipleConstructor = null;
+        withOneConstructor = null;
+        withNoArgConstructor = null;
+        withThrowingConstructor = null;
+        withVarargConstructor = null;
+    }
+
+    @Mock private ConstructorArgumentResolver resolver;
+
+    @Test
+    public void should_be_created_with_an_argument_resolver() throws Exception {
+        new ParameterizedConstructorInstantiator(this, field("whateverForNow"), resolver);
+    }
+
+    @Test
+    public void should_fail_if_no_parameterized_constructor_found___excluding_inner_and_others_kind_of_types() throws Exception {
+        try {
+            new ParameterizedConstructorInstantiator(this, field("withNoArgConstructor"), resolver).instantiate();
+            fail();
+        } catch (MockitoException me) {
+            assertThat(me.getMessage()).contains("no parameterized constructor").contains("withNoArgConstructor").contains("NoArgConstructor");
+        }
+    }
+
+    @Test
+    public void should_instantiate_type_if_resolver_provide_matching_types() throws Exception {
+        Observer observer = mock(Observer.class);
+        Map map = mock(Map.class);
+        given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ observer, map });
+
+        new ParameterizedConstructorInstantiator(this, field("withMultipleConstructor"), resolver).instantiate();
+
+        assertNotNull(withMultipleConstructor);
+        assertNotNull(withMultipleConstructor.observer);
+        assertNotNull(withMultipleConstructor.map);
+    }
+
+    @Test
+    public void should_fail_if_an_argument_instance_type_do_not_match_wanted_type() throws Exception {
+        Observer observer = mock(Observer.class);
+        Set<?> wrongArg = mock(Set.class);
+        given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ observer, wrongArg });
+
+        try {
+            new ParameterizedConstructorInstantiator(this, field("withMultipleConstructor"), resolver).instantiate();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage()).contains("argResolver").contains("incorrect types");
+        }
+    }
+
+    @Test
+    public void should_report_failure_if_constructor_throws_exception() throws Exception {
+        given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ null });
+
+        try {
+            new ParameterizedConstructorInstantiator(this, field("withThrowingConstructor"), resolver).instantiate();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage()).contains("constructor").contains("raised an exception");
+        }
+    }
+
+    @Test
+    public void should_instantiate_type_with_vararg_constructor() throws Exception {
+        Observer[] vararg = new Observer[] {  };
+        given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ "", vararg});
+
+        new ParameterizedConstructorInstantiator(this, field("withVarargConstructor"), resolver).instantiate();
+
+        assertNotNull(withVarargConstructor);
+    }
+
+    private Field field(String fieldName) throws NoSuchFieldException {
+        Field field = this.getClass().getDeclaredField(fieldName);
+        field.setAccessible(true);
+        return field;
+    }
+
+    private static class NoArgConstructor {
+        NoArgConstructor() { }
+    }
+
+    private static class OneConstructor {
+        public OneConstructor(Observer observer) { }
+    }
+
+    private static class ThrowingConstructor {
+        public ThrowingConstructor(Observer observer) throws IOException { throw new IOException(); }
+    }
+
+    private static class MultipleConstructor extends OneConstructor {
+        Observer observer;
+        Map map;
+
+        public MultipleConstructor(Observer observer) { this(observer, null); }
+        public MultipleConstructor(Observer observer, Map map) {
+            super(observer);
+            this.observer = observer;
+            this.map = map;
+        }
+    }
+
+    private static class VarargConstructor {
+        VarargConstructor(String whatever, Observer... observers) { }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/util/reflection/SuperTypesLastSorterTest.java b/src/test/java/org/mockito/internal/util/reflection/SuperTypesLastSorterTest.java
new file mode 100644
index 0000000..02cfd10
--- /dev/null
+++ b/src/test/java/org/mockito/internal/util/reflection/SuperTypesLastSorterTest.java
@@ -0,0 +1,137 @@
+package org.mockito.internal.util.reflection;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.util.reflection.SuperTypesLastSorter.sortSuperTypesLast;
+
+@SuppressWarnings("unused")
+public class SuperTypesLastSorterTest {
+    /**
+     * A Comparator that behaves like the old one, so the existing tests
+     * continue to work.
+     */
+    private static Comparator<Field> cmp = new Comparator<Field>() {
+        public int compare(Field o1, Field o2) {
+            if (o1.equals(o2)) {
+                return 0;
+            }
+
+            List<Field> l = sortSuperTypesLast(Arrays.asList(o1, o2));
+
+            if (l.get(0) == o1) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+    };
+
+    private Object objectA;
+    private Object objectB;
+
+    private Number numberA;
+    private Number numberB;
+
+    private Integer integerA;
+    private Integer integerB;
+
+    private Iterable<?> iterableA;
+
+    private Number xNumber;
+    private Iterable<?> yIterable;
+    private Integer zInteger;
+
+
+    @Test
+    public void when_same_type_the_order_is_based_on_field_name() throws Exception {
+        assertThat(cmp.compare(field("objectA"), field("objectB"))).isEqualTo(-1);
+        assertThat(cmp.compare(field("objectB"), field("objectA"))).isEqualTo(1);
+        assertThat(cmp.compare(field("objectB"), field("objectB"))).isEqualTo(0);
+    }
+
+    @Test
+    public void when_type_is_different_the_supertype_comes_last() throws Exception {
+        assertThat(cmp.compare(field("numberA"), field("objectB"))).isEqualTo(-1);
+        assertThat(cmp.compare(field("objectB"), field("numberA"))).isEqualTo(1);
+    }
+
+    @Test
+    public void using_Collections_dot_sort() throws Exception {
+        List<Field> unsortedFields = Arrays.asList(
+                field("objectB"),
+                field("integerB"),
+                field("numberA"),
+                field("numberB"),
+                field("objectA"),
+                field("integerA")
+        );
+
+        List<Field> sortedFields =  sortSuperTypesLast(unsortedFields);
+
+        assertThat(sortedFields).containsSequence(
+                field("integerA"),
+                field("integerB"),
+                field("numberA"),
+                field("numberB"),
+                field("objectA"),
+                field("objectB")
+        );
+    }
+
+
+    @Test
+    public void issue_352_order_was_different_between_JDK6_and_JDK7() throws Exception {
+        List<Field> unsortedFields = Arrays.asList(
+                field("objectB"),
+                field("objectA")
+        );
+
+        Collections.sort(unsortedFields, cmp);
+
+        assertThat(unsortedFields).containsSequence(
+                field("objectA"),
+                field("objectB")
+        );
+    }
+
+    @Test
+    public void fields_sort_consistently_when_interfaces_are_included() throws NoSuchFieldException {
+        assertSortConsistently(field("iterableA"), field("numberA"), field("integerA"));
+    }
+
+    @Test
+    public void fields_sort_consistently_when_names_and_type_indicate_different_order() throws NoSuchFieldException {
+        assertSortConsistently(field("xNumber"), field("yIterable"), field("zInteger"));
+    }
+
+    /**
+     * Assert that these fields sort in the same order no matter which order
+     * they start in.
+     */
+    private static void assertSortConsistently(Field a, Field b, Field c) {
+        Field[][] initialOrderings = {
+                {a, b, c},
+                {a, c, b},
+                {b, a, c},
+                {b, c, a},
+                {c, a, b},
+                {c, b, a}
+        };
+
+        Set<List<Field>> results = new HashSet<List<Field>>();
+
+        for (Field[] o : initialOrderings) {
+            results.add(sortSuperTypesLast(Arrays.asList(o)));
+        }
+
+        assertThat(results).hasSize(1);
+    }
+
+    private Field field(String field) throws NoSuchFieldException {
+        return getClass().getDeclaredField(field);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/DefaultRegisteredInvocationsTest.java b/src/test/java/org/mockito/internal/verification/DefaultRegisteredInvocationsTest.java
new file mode 100644
index 0000000..34ee5b0
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/DefaultRegisteredInvocationsTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+public class DefaultRegisteredInvocationsTest extends TestBase {
+
+    private DefaultRegisteredInvocations invocations;
+
+    @Before
+    public void setup() {
+        invocations = new DefaultRegisteredInvocations();
+    }
+
+    @Test
+    public void should_not_return_to_string_method() throws Exception {
+        Invocation toString = new InvocationBuilder().method("toString").toInvocation();
+        Invocation simpleMethod = new InvocationBuilder().simpleMethod().toInvocation();
+
+        invocations.add(toString);
+        invocations.add(simpleMethod);
+
+        assertTrue(invocations.getAll().contains(simpleMethod));
+        assertFalse(invocations.getAll().contains(toString));
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/DescriptionTest.java b/src/test/java/org/mockito/internal/verification/DescriptionTest.java
new file mode 100644
index 0000000..b88a92f
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/DescriptionTest.java
@@ -0,0 +1,52 @@
+package org.mockito.internal.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationMode;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+public class DescriptionTest {
+
+    @Mock
+    private VerificationMode mockVerificationMode;
+
+    @Mock
+    private VerificationData mockVerificationData;
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+    }
+
+    /**
+     * Test of verify method, of class Description. This test validates that the custom message is prepended to the
+     * error message when verification fails.
+     */
+    @Test
+    public void verification_failure_should_prepend_expected_message() {
+        String failureMessage = "message should be prepended to the original message";
+        String exceptionMessage = "original error message";
+        String expectedResult = failureMessage + "\n" + exceptionMessage;
+        MockitoAssertionError error = new MockitoAssertionError(exceptionMessage);
+        doThrow(error).when(mockVerificationMode).verify(mockVerificationData);
+
+        Description instance = new Description(mockVerificationMode, failureMessage);
+
+        try {
+            instance.verify(mockVerificationData);
+            verify(mockVerificationMode).verify(mockVerificationData);
+            fail("Should not have made it this far");
+
+        } catch (MockitoAssertionError e) {
+            assertEquals(expectedResult, e.getMessage());
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/DummyVerificationMode.java b/src/test/java/org/mockito/internal/verification/DummyVerificationMode.java
new file mode 100644
index 0000000..db86511
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/DummyVerificationMode.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationMode;
+
+public class DummyVerificationMode implements VerificationMode {
+    public void verify(VerificationData data) {
+    }
+
+    public VerificationMode description(String description) {
+        return new DummyVerificationMode();
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/NoMoreInteractionsTest.java b/src/test/java/org/mockito/internal/verification/NoMoreInteractionsTest.java
new file mode 100644
index 0000000..3873ff9
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/NoMoreInteractionsTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.stubbing.InvocationContainerImpl;
+import org.mockito.internal.verification.api.VerificationDataInOrderImpl;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.mock;
+
+public class NoMoreInteractionsTest extends TestBase {
+
+    InOrderContextImpl context = new InOrderContextImpl();
+
+    @Test
+    public void shouldVerifyInOrder() {
+        //given
+        NoMoreInteractions n = new NoMoreInteractions();
+        Invocation i = new InvocationBuilder().toInvocation();
+        assertFalse(context.isVerified(i));
+
+        try {
+            //when
+            n.verifyInOrder(new VerificationDataInOrderImpl(context, asList(i), null));
+            //then
+            fail();
+        } catch(VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldVerifyInOrderAndPass() {
+        //given
+        NoMoreInteractions n = new NoMoreInteractions();
+        Invocation i = new InvocationBuilder().toInvocation();
+        context.markVerified(i);
+        assertTrue(context.isVerified(i));
+
+        //when
+        n.verifyInOrder(new VerificationDataInOrderImpl(context, asList(i), null));
+        //then no exception is thrown
+    }
+
+    @Test
+    public void shouldVerifyInOrderMultipleInvoctions() {
+        //given
+        NoMoreInteractions n = new NoMoreInteractions();
+        Invocation i = new InvocationBuilder().seq(1).toInvocation();
+        Invocation i2 = new InvocationBuilder().seq(2).toInvocation();
+
+        //when
+        context.markVerified(i2);
+
+        //then no exception is thrown
+        n.verifyInOrder(new VerificationDataInOrderImpl(context, asList(i, i2), null));
+    }
+
+    @Test
+    public void shouldVerifyInOrderMultipleInvoctionsAndThrow() {
+        //given
+        NoMoreInteractions n = new NoMoreInteractions();
+        Invocation i = new InvocationBuilder().seq(1).toInvocation();
+        Invocation i2 = new InvocationBuilder().seq(2).toInvocation();
+
+        try {
+            //when
+            n.verifyInOrder(new VerificationDataInOrderImpl(context, asList(i, i2), null));
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void noMoreInteractionsExceptionMessageShouldDescribeMock() {
+        //given
+        NoMoreInteractions n = new NoMoreInteractions();
+        IMethods mock = mock(IMethods.class, "a mock");
+        InvocationMatcher i = new InvocationBuilder().mock(mock).toInvocationMatcher();
+
+        InvocationContainerImpl invocations =
+            new InvocationContainerImpl( new MockSettingsImpl());
+        invocations.setInvocationForPotentialStubbing(i);
+
+        try {
+            //when
+            n.verify(new VerificationDataImpl(invocations, null));
+            //then
+            fail();
+        } catch (NoInteractionsWanted e) {
+            Assertions.assertThat(e.toString()).contains(mock.toString());
+        }
+    }
+
+    @Test
+    public void noMoreInteractionsInOrderExceptionMessageShouldDescribeMock() {
+        //given
+        NoMoreInteractions n = new NoMoreInteractions();
+        IMethods mock = mock(IMethods.class, "a mock");
+        Invocation i = new InvocationBuilder().mock(mock).toInvocation();
+
+        try {
+            //when
+            n.verifyInOrder(new VerificationDataInOrderImpl(context, asList(i), null));
+            //then
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            Assertions.assertThat(e.toString()).contains(mock.toString());
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/OnlyTest.java b/src/test/java/org/mockito/internal/verification/OnlyTest.java
new file mode 100644
index 0000000..13df278
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/OnlyTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.MatchableInvocation;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class OnlyTest {
+
+    Only only = new Only();
+
+    public class VerificationDataStub implements VerificationData {
+        private final Invocation invocation;
+        private final InvocationMatcher wanted;
+
+        public VerificationDataStub(InvocationMatcher wanted, Invocation invocation) {
+            this.invocation = invocation;
+            this.wanted = wanted;
+        }
+
+        public List<Invocation> getAllInvocations() {
+            return Arrays.asList(invocation);
+        }
+
+        @Override
+        public MatchableInvocation getTarget() {
+            return wanted;
+        }
+
+        public InvocationMatcher getWanted() {
+            return wanted;
+        }
+    }
+
+    @Test
+    public void shouldMarkAsVerified() {
+        //given
+        Invocation invocation = new InvocationBuilder().toInvocation();
+        assertFalse(invocation.isVerified());
+
+        //when
+        only.verify(new VerificationDataStub(new InvocationMatcher(invocation), invocation));
+
+        //then
+        assertTrue(invocation.isVerified());
+    }
+
+    @Test
+    public void shouldNotMarkAsVerifiedWhenAssertionFailed() {
+        //given
+        Invocation invocation = new InvocationBuilder().toInvocation();
+        assertFalse(invocation.isVerified());
+
+        //when
+        try {
+            only.verify(new VerificationDataStub(new InvocationBuilder().toInvocationMatcher(), invocation));
+            fail();
+        } catch (MockitoAssertionError e) {}
+
+        //then
+        assertFalse(invocation.isVerified());
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/SmartPrinterTest.java b/src/test/java/org/mockito/internal/verification/SmartPrinterTest.java
new file mode 100644
index 0000000..6c760ee
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/SmartPrinterTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.reporting.SmartPrinter;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+public class SmartPrinterTest extends TestBase {
+
+    private InvocationMatcher multi;
+    private InvocationMatcher shortie;
+    @Mock private IMethods mock;
+
+    @Before
+    public void setup() throws Exception {
+        mock.varargs("first very long argument", "second very long argument", "another very long argument");
+        multi = new InvocationMatcher(getLastInvocation());
+
+        mock.varargs("short arg");
+        shortie = new InvocationMatcher(getLastInvocation());
+    }
+
+    @Test
+    public void shouldPrintBothInMultilinesWhenFirstIsMulti() {
+        //when
+        SmartPrinter printer = new SmartPrinter(multi, shortie.getInvocation());
+
+        //then
+        assertThat(printer.getWanted().toString()).contains("\n");
+        assertThat(printer.getActual().toString()).contains("\n");
+    }
+
+    @Test
+    public void shouldPrintBothInMultilinesWhenSecondIsMulti() {
+        //when
+        SmartPrinter printer = new SmartPrinter(shortie, multi.getInvocation());
+
+        //then
+        assertThat(printer.getWanted().toString()).contains("\n");
+        assertThat(printer.getActual().toString()).contains("\n");
+    }
+
+    @Test
+    public void shouldPrintBothInMultilinesWhenBothAreMulti() {
+        //when
+        SmartPrinter printer = new SmartPrinter(multi, multi.getInvocation());
+
+        //then
+        assertThat(printer.getWanted().toString()).contains("\n");
+        assertThat(printer.getActual().toString()).contains("\n");
+    }
+
+    @Test
+    public void shouldPrintBothInSingleLineWhenBothAreShort() {
+        //when
+        SmartPrinter printer = new SmartPrinter(shortie, shortie.getInvocation());
+
+        //then
+        assertThat(printer.getWanted().toString()).doesNotContain("\n");
+        assertThat(printer.getActual().toString()).doesNotContain("\n");
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/VerificationDataImplTest.java b/src/test/java/org/mockito/internal/verification/VerificationDataImplTest.java
new file mode 100644
index 0000000..cc2daba
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/VerificationDataImplTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+
+public class VerificationDataImplTest extends TestBase {
+
+    @Test
+    public void shouldToStringBeNotVerifiable() throws Exception {
+        InvocationMatcher toString = new InvocationBuilder().method("toString").toInvocationMatcher();
+        try {
+            new VerificationDataImpl(null, toString);
+            fail();
+        } catch (MockitoException e) {}
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java b/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java
new file mode 100644
index 0000000..54a7684
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java
@@ -0,0 +1,64 @@
+package org.mockito.internal.verification;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockito.verification.VerificationMode;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+public class VerificationOverTimeImplTest {
+    @Mock
+    private VerificationMode delegate;
+    private VerificationOverTimeImpl impl;
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        impl = new VerificationOverTimeImpl(10, 1000, delegate, true);
+    }
+
+    @Test
+    public void should_return_on_success() {
+        impl.verify(null);
+        verify(delegate).verify(null);
+    }
+
+    @Test
+    public void should_throw_mockito_assertion_error() {
+        MockitoAssertionError toBeThrown = new MockitoAssertionError("message");
+        exception.expect(is(toBeThrown));
+
+        doThrow(toBeThrown).when(delegate).verify(null);
+        impl.verify(null);
+    }
+
+    @Test
+    public void should_deal_with_junit_assertion_error() {
+        ArgumentsAreDifferent toBeThrown = new ArgumentsAreDifferent("message", "wanted", "actual");
+        exception.expect(is(toBeThrown));
+        exception.expectMessage("message");
+
+        doThrow(toBeThrown).when(delegate).verify(null);
+        impl.verify(null);
+    }
+
+    @Test
+    public void should_not_wrap_other_exceptions() {
+        RuntimeException toBeThrown = new RuntimeException();
+        exception.expect(is(toBeThrown));
+
+        doThrow(toBeThrown).when(delegate).verify(null);
+        impl.verify(null);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/VerificationWithDescriptionTest.java b/src/test/java/org/mockito/internal/verification/VerificationWithDescriptionTest.java
new file mode 100644
index 0000000..b79fa4d
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/VerificationWithDescriptionTest.java
@@ -0,0 +1,38 @@
+package org.mockito.internal.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.assertj.core.api.Assertions.fail;
+import static org.mockito.Mockito.description;
+import static org.mockito.Mockito.verify;
+
+public class VerificationWithDescriptionTest {
+
+    @Mock
+    private List<?> mock;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void assertion_error_message_should_start_with_the_custom_specified_message() {
+
+        String failureMessage = "Verification failed!";
+        try {
+            verify(mock, description(failureMessage)).clear();
+            fail("Should not have made it this far");
+
+        } catch (MockitoAssertionError e) {
+            assertTrue(e.getMessage().startsWith(failureMessage));
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingToolTest.java b/src/test/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingToolTest.java
new file mode 100644
index 0000000..3af2add
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingToolTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.argumentmatching;
+
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.ContainsExtraTypeInfo;
+import org.mockito.internal.matchers.Equals;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static java.util.Collections.singletonList;
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.*;
+
+@SuppressWarnings({ "unchecked", "serial" })
+public class ArgumentMatchingToolTest extends TestBase {
+
+    @Test
+    public void shouldNotFindAnySuspiciousMatchersWhenNumberOfArgumentsDoesntMatch() {
+        // given
+        List<ArgumentMatcher> matchers = (List) Arrays.asList(new Equals(1));
+
+        // when
+        Integer[] suspicious = ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes(matchers, new Object[] { 10, 20 });
+
+        // then
+        assertEquals(0, suspicious.length);
+    }
+
+    @Test
+    public void shouldNotFindAnySuspiciousMatchersWhenArgumentsMatch() {
+        // given
+        List<ArgumentMatcher> matchers = (List) Arrays.asList(new Equals(10), new Equals(20));
+
+        // when
+        Integer[] suspicious = ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes(matchers, new Object[] { 10, 20 });
+
+        // then
+        assertEquals(0, suspicious.length);
+    }
+
+    @Test
+    public void shouldFindSuspiciousMatchers() {
+        // given
+        Equals matcherInt20 = new Equals(20);
+        Long longPretendingAnInt = 20L;
+
+        // when
+        List<ArgumentMatcher> matchers = (List) Arrays.asList(new Equals(10), matcherInt20);
+        Integer[] suspicious = ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes(matchers, new Object[] { 10, longPretendingAnInt });
+
+        // then
+        assertEquals(1, suspicious.length);
+        assertEquals(new Integer(1), suspicious[0]);
+    }
+
+    @Test
+    public void shouldNotFindSuspiciousMatchersWhenTypesAreTheSame() {
+        // given
+        Equals matcherWithBadDescription = new Equals(20) {
+            public String toString() {
+                return "10";
+            }
+        };
+        Integer argument = 10;
+
+        // when
+        Integer[] suspicious = ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes((List) Arrays.asList(matcherWithBadDescription), new Object[] { argument });
+
+        // then
+        assertEquals(0, suspicious.length);
+    }
+
+    @Test
+    public void shouldWorkFineWhenGivenArgIsNull() {
+        // when
+        Integer[] suspicious = ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes((List) Arrays.asList(new Equals(20)), new Object[] { null });
+
+        // then
+        assertEquals(0, suspicious.length);
+    }
+
+
+    /**
+     *
+     */
+    @Test
+    @SuppressWarnings("rawtypes")
+    public void shouldUseMatchersSafely() {
+        /** This matcher is evil cause typeMatches(Object) returns true for every passed type but matches(T)
+         * method accepts only Strings. When a Integer is passed (thru the matches(Object) bridge method )  a
+         * ClassCastException will be thrown. */
+        class StringMatcher implements ArgumentMatcher<String>, ContainsExtraTypeInfo {
+            @Override
+            public boolean matches(String item) {
+                return true; // in this test we never get here
+            }
+
+            @Override
+            public String toStringWithType() {
+                return "";
+            }
+
+            @Override
+            public boolean typeMatches(Object target) {
+                return true;
+            }
+        }
+
+        // given
+        List<ArgumentMatcher> matchers = (List) singletonList(new StringMatcher());
+
+        // when
+        Integer[] suspicious = ArgumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes(matchers, new Object[] { 10 });
+
+        // then
+        assertEquals(0, suspicious.length);
+    }
+
+}
diff --git a/src/test/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsCheckerTest.java b/src/test/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsCheckerTest.java
new file mode 100644
index 0000000..c4a54c4
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsCheckerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.checkers;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.verification.InOrderContextImpl;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.internal.verification.checkers.AtLeastXNumberOfInvocationsChecker.checkAtLeastNumberOfInvocations;
+
+public class AtLeastXNumberOfInvocationsCheckerTest   {
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    @Test
+    public void shouldMarkActualInvocationsAsVerifiedInOrder() {
+        InOrderContext context = new InOrderContextImpl();
+        //given
+        Invocation invocation = new InvocationBuilder().simpleMethod().toInvocation();
+        Invocation invocationTwo = new InvocationBuilder().differentMethod().toInvocation();
+
+        //when
+        checkAtLeastNumberOfInvocations(asList(invocation, invocationTwo), new InvocationMatcher(invocation), 1, context);
+
+        //then
+        assertThat(invocation.isVerified()).isTrue();
+    }
+
+    @Test
+    public void shouldReportTooLittleInvocationsInOrder() {
+        InOrderContext context = new InOrderContextImpl();
+        //given
+        Invocation invocation = new InvocationBuilder().simpleMethod().toInvocation();
+        Invocation invocationTwo = new InvocationBuilder().differentMethod().toInvocation();
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("iMethods.simpleMethod()");
+        exception.expectMessage("Wanted *at least* 2 times");
+        exception.expectMessage("But was 1 time");
+
+        //when
+        checkAtLeastNumberOfInvocations(asList(invocation, invocationTwo), new InvocationMatcher(invocation), 2, context);
+
+
+    }
+
+    @Test
+    public void shouldMarkActualInvocationsAsVerified() {
+        //given
+        Invocation invocation = new InvocationBuilder().simpleMethod().toInvocation();
+        Invocation invocationTwo = new InvocationBuilder().differentMethod().toInvocation();
+
+        //when
+        checkAtLeastNumberOfInvocations(asList(invocation, invocationTwo), new InvocationMatcher(invocation), 1);
+
+        //then
+        assertThat(invocation.isVerified()).isTrue();
+    }
+
+    @Test
+    public void shouldReportTooLittleInvocations() {
+        //given
+        Invocation invocation = new InvocationBuilder().simpleMethod().toInvocation();
+        Invocation invocationTwo = new InvocationBuilder().differentMethod().toInvocation();
+
+        exception.expect(TooLittleActualInvocations.class);
+        exception.expectMessage("iMethods.simpleMethod()");
+        exception.expectMessage("Wanted *at least* 2 times");
+        exception.expectMessage("But was 1 time");
+
+        //when
+        checkAtLeastNumberOfInvocations(asList(invocation, invocationTwo), new InvocationMatcher(invocation), 2);
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/checkers/MissingInvocationCheckerTest.java b/src/test/java/org/mockito/internal/verification/checkers/MissingInvocationCheckerTest.java
new file mode 100644
index 0000000..4ce557e
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/checkers/MissingInvocationCheckerTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import static java.util.Arrays.asList;
+
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+public class MissingInvocationCheckerTest extends TestBase {
+
+	private InvocationMatcher wanted;
+	private List<Invocation> invocations;
+
+	@Mock
+	private IMethods mock;
+
+	@Rule
+	public ExpectedException exception = ExpectedException.none();
+
+	@Test
+	public void shouldPassBecauseActualInvocationFound() {
+		wanted = buildSimpleMethod().toInvocationMatcher();
+		invocations = asList(buildSimpleMethod().toInvocation());
+
+		MissingInvocationChecker.checkMissingInvocation(invocations, wanted);
+	}
+
+	@Test
+	public void shouldReportWantedButNotInvoked() {
+		wanted = buildSimpleMethod().toInvocationMatcher();
+		invocations = asList(buildDifferentMethod().toInvocation());
+
+		exception.expect(WantedButNotInvoked.class);
+		exception.expectMessage("Wanted but not invoked:");
+		exception.expectMessage("mock.simpleMethod()");
+		exception.expectMessage("However, there was exactly 1 interaction with this mock:");
+		exception.expectMessage("mock.differentMethod();");
+
+		MissingInvocationChecker.checkMissingInvocation(invocations, wanted);
+	}
+
+	@Test
+	public void shouldReportWantedInvocationDiffersFromActual() {
+		wanted = buildIntArgMethod().arg(2222).toInvocationMatcher();
+		invocations = asList(buildIntArgMethod().arg(1111).toInvocation());
+
+		exception.expect(ArgumentsAreDifferent.class);
+
+		exception.expectMessage("Argument(s) are different! Wanted:");
+		exception.expectMessage("mock.intArgumentMethod(2222);");
+		exception.expectMessage("Actual invocation has different arguments:");
+		exception.expectMessage("mock.intArgumentMethod(1111);");
+
+		MissingInvocationChecker.checkMissingInvocation(invocations, wanted);
+	}
+
+	private InvocationBuilder buildIntArgMethod() {
+		return new InvocationBuilder().mock(mock).method("intArgumentMethod").argTypes(int.class);
+	}
+
+	private InvocationBuilder buildSimpleMethod() {
+		return new InvocationBuilder().mock(mock).simpleMethod();
+	}
+
+	private InvocationBuilder buildDifferentMethod() {
+		return new InvocationBuilder().mock(mock).differentMethod();
+	}
+}
diff --git a/src/test/java/org/mockito/internal/verification/checkers/MissingInvocationInOrderCheckerTest.java b/src/test/java/org/mockito/internal/verification/checkers/MissingInvocationInOrderCheckerTest.java
new file mode 100644
index 0000000..a86122f
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/checkers/MissingInvocationInOrderCheckerTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.progress.VerificationModeBuilder;
+import org.mockito.internal.verification.InOrderContextImpl;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.mockito.internal.verification.checkers.MissingInvocationChecker.checkMissingInvocation;
+
+public class MissingInvocationInOrderCheckerTest  {
+
+	private InvocationMatcher wanted;
+	private List<Invocation> invocations;
+
+	@Mock
+	private IMethods mock;
+
+	@Rule
+	public ExpectedException exception = ExpectedException.none();
+
+	@Rule
+	public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+    private InOrderContext context = new InOrderContextImpl();
+
+    @Before
+    public void setup() {
+    }
+
+    @Test
+    public void shouldPassWhenMatchingInteractionFound() throws Exception {
+
+    	invocations = asList(buildSimpleMethod().toInvocation());
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        checkMissingInvocation(invocations, wanted, context);
+    }
+
+    @Test
+    public void shouldReportWantedButNotInvoked() throws Exception {
+    	invocations = asList(buildDifferentMethod().toInvocation());
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(WantedButNotInvoked.class);
+		exception.expectMessage("Wanted but not invoked:");
+		exception.expectMessage("mock.simpleMethod()");
+
+        checkMissingInvocation(invocations, wanted, context);
+    }
+
+    @Test
+    public void shouldReportArgumentsAreDifferent() throws Exception {
+    	invocations = asList(buildIntArgMethod().arg(1111).toInvocation());
+        wanted = buildIntArgMethod().arg(2222).toInvocationMatcher();
+
+        exception.expect(ArgumentsAreDifferent.class);
+
+		exception.expectMessage("Argument(s) are different! Wanted:");
+		exception.expectMessage("mock.intArgumentMethod(2222);");
+		exception.expectMessage("Actual invocation has different arguments:");
+		exception.expectMessage("mock.intArgumentMethod(1111);");
+
+    	checkMissingInvocation(invocations, wanted, context);
+
+     }
+
+    @Test
+    public void shouldReportWantedDiffersFromActual() throws Exception {
+
+    	Invocation invocation1 = buildIntArgMethod().arg(1111).toInvocation();
+    	Invocation invocation2 = buildIntArgMethod().arg(2222).toInvocation();
+
+    	context.markVerified(invocation2);
+		invocations = asList(invocation1,invocation2);
+        wanted = buildIntArgMethod().arg(2222).toInvocationMatcher();
+
+        exception.expect(VerificationInOrderFailure.class);
+
+		exception.expectMessage("Verification in order failure");
+		exception.expectMessage("Wanted but not invoked:");
+		exception.expectMessage("mock.intArgumentMethod(2222);");
+		exception.expectMessage("Wanted anywhere AFTER following interaction:");
+		exception.expectMessage("mock.intArgumentMethod(2222);");
+
+        checkMissingInvocation(invocations, wanted, context);
+    }
+
+    private InvocationBuilder buildIntArgMethod() {
+		return new InvocationBuilder().mock(mock).method("intArgumentMethod").argTypes(int.class);
+	}
+
+	private InvocationBuilder buildSimpleMethod() {
+		return new InvocationBuilder().mock(mock).simpleMethod();
+	}
+
+	private InvocationBuilder buildDifferentMethod() {
+		return new InvocationBuilder().mock(mock).differentMethod();
+	}
+
+
+}
diff --git a/src/test/java/org/mockito/internal/verification/checkers/NumberOfInvocationsCheckerTest.java b/src/test/java/org/mockito/internal/verification/checkers/NumberOfInvocationsCheckerTest.java
new file mode 100644
index 0000000..af9d3cb
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/checkers/NumberOfInvocationsCheckerTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.NeverWantedButInvoked;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.TooManyActualInvocations;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NumberOfInvocationsCheckerTest {
+
+    private InvocationMatcher wanted;
+
+    private List<Invocation> invocations;
+
+    @Mock
+    private IMethods mock;
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    @Rule
+    public TestName testName = new TestName();
+
+    @Test
+    public void shouldReportTooLittleActual() throws Exception {
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
+
+        exception.expect(TooLittleActualInvocations.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 100 times");
+        exception.expectMessage("But was 2 times");
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
+    }
+
+    @Test
+    public void shouldReportWithLastInvocationStackTrace() throws Exception {
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
+
+        exception.expect(TooLittleActualInvocations.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 100 times");
+        exception.expectMessage("But was 2 times");
+        exception.expectMessage(containsTimes("-> at", 2));
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
+    }
+
+    @Test
+    public void shouldNotReportWithLastInvocationStackTraceIfNoInvocationsFound() throws Exception {
+        invocations = emptyList();
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(TooLittleActualInvocations.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 100 times");
+        exception.expectMessage("But was 0 times");
+        exception.expectMessage(containsTimes("-> at", 1));
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
+    }
+
+    @Test
+    public void shouldReportWithFirstUndesiredInvocationStackTrace() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+        Invocation second = buildSimpleMethod().toInvocation();
+        Invocation third = buildSimpleMethod().toInvocation();
+
+        invocations = asList(first, second, third);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(TooManyActualInvocations.class);
+        exception.expectMessage("" + third.getLocation());
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 2);
+    }
+
+    @Test
+    public void shouldReportTooManyActual() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+        Invocation second = buildSimpleMethod().toInvocation();
+
+        invocations = asList(first, second);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expectMessage("Wanted 1 time");
+        exception.expectMessage("But was 2 times");
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1);
+    }
+
+    @Test
+    public void shouldReportNeverWantedButInvoked() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+
+        invocations = asList(first);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(NeverWantedButInvoked.class);
+        exception.expectMessage("Never wanted here");
+        exception.expectMessage("But invoked here");
+        exception.expectMessage("" + first.getLocation());
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0);
+    }
+
+	@Test
+	public void shouldMarkInvocationsAsVerified() throws Exception {
+		Invocation invocation = buildSimpleMethod().toInvocation();
+		assertThat(invocation.isVerified()).isFalse();
+
+		invocations = asList(invocation);
+		wanted = buildSimpleMethod().toInvocationMatcher();
+		NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1);
+		assertThat(invocation.isVerified()).isTrue();
+	}
+
+    private InvocationBuilder buildSimpleMethod() {
+        return new InvocationBuilder().mock(mock).simpleMethod();
+    }
+
+    private static BaseMatcher<String> containsTimes(String value, int amount) {
+        return new StringContainsNumberMatcher(value, amount);
+    }
+
+    private static class StringContainsNumberMatcher extends TypeSafeMatcher<String> {
+
+        private final String expected;
+
+        private final int amount;
+
+        StringContainsNumberMatcher(String expected, int amount) {
+            this.expected = expected;
+            this.amount = amount;
+        }
+
+        public boolean matchesSafely(String text) {
+            int lastIndex = 0;
+            int count = 0;
+            while (lastIndex != -1) {
+                lastIndex = text.indexOf(expected, lastIndex);
+                if (lastIndex != -1) {
+                    count++;
+                    lastIndex += expected.length();
+                }
+            }
+            return count == amount;
+        }
+
+        public void describeTo(Description description) {
+            description.appendText("containing '" + expected + "' exactly " + amount + " times");
+        }
+
+    }
+}
diff --git a/src/test/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderCheckerTest.java b/src/test/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderCheckerTest.java
new file mode 100644
index 0000000..2e72033
--- /dev/null
+++ b/src/test/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderCheckerTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.util.List;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.verification.InOrderContextImpl;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+
+public class NumberOfInvocationsInOrderCheckerTest {
+
+    private InvocationMatcher wanted;
+    private List<Invocation> invocations;
+    private InOrderContext context;
+
+    private IMethods mock;
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    @Before
+    public void setup() {
+        context = new InOrderContextImpl();
+        mock = mock(IMethods.class, "mock");
+
+    }
+
+    @Test
+    public void shouldPassIfWantedIsZeroAndMatchingChunkIsEmpty() {
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = emptyList();
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0, context);
+    }
+
+    @Test
+    public void shouldPassIfChunkMatches() throws Exception {
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = asList(buildSimpleMethod().toInvocation());
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
+    }
+
+    @Test
+    public void shouldReportTooLittleInvocations() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+        Invocation second = buildSimpleMethod().toInvocation();
+
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = asList(first, second);
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 4 times");
+        exception.expectMessage("But was 2 times");
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 4, context);
+    }
+
+    @Test
+    public void shouldMarkAsVerifiedInOrder() throws Exception {
+        Invocation invocation = buildSimpleMethod().toInvocation();
+
+        invocations = asList(invocation);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        assertThat(context.isVerified(invocation)).isFalse();
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
+        assertThat(context.isVerified(invocation)).isTrue();
+    }
+
+    @Test
+    public void shouldReportTooLittleActual() throws Exception {
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 100 times");
+        exception.expectMessage("But was 2 times");
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100, context);
+    }
+
+    @Test
+    public void shouldReportWithLastInvocationStackTrace() throws Exception {
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 100 times");
+        exception.expectMessage("But was 2 times");
+        exception.expectMessage(containsTimes("-> at", 2));
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100, context);
+
+    }
+
+    @Test
+    public void shouldNotReportWithLastInvocationStackTraceIfNoInvocationsFound() throws Exception {
+        invocations = emptyList();
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 100 times");
+        exception.expectMessage("But was 0 times");
+        exception.expectMessage(containsTimes("-> at", 1));
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100, context);
+    }
+
+    @Test
+    public void shouldReportWithFirstUndesiredInvocationStackTrace() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+        Invocation second = buildSimpleMethod().toInvocation();
+        Invocation third = buildSimpleMethod().toInvocation();
+
+        invocations = asList(first, second, third);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("" + third.getLocation());
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 2, context);
+    }
+
+    @Test
+    public void shouldReportTooManyActual() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+        Invocation second = buildSimpleMethod().toInvocation();
+
+        invocations = asList(first, second);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expectMessage("Wanted 1 time");
+        exception.expectMessage("But was 2 times");
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
+    }
+
+    @Test
+    public void shouldReportNeverWantedButInvoked() throws Exception {
+        Invocation first = buildSimpleMethod().toInvocation();
+
+        invocations = asList(first);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+
+        exception.expect(VerificationInOrderFailure.class);
+        exception.expectMessage("mock.simpleMethod()");
+        exception.expectMessage("Wanted 0 times");
+        exception.expectMessage("But was 1 time. Undesired invocation");
+        exception.expectMessage("" + first.getLocation());
+
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0, context);
+    }
+
+    @Test
+    public void shouldMarkInvocationsAsVerified() throws Exception {
+        Invocation invocation = buildSimpleMethod().toInvocation();
+        assertThat(invocation.isVerified()).isFalse();
+
+        invocations = asList(invocation);
+        wanted = buildSimpleMethod().toInvocationMatcher();
+        NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
+        assertThat(invocation.isVerified()).isTrue();
+    }
+
+    private static BaseMatcher<String> containsTimes(String value, int amount) {
+        return new StringContainsNumberMatcher(value, amount);
+    }
+
+    private static class StringContainsNumberMatcher extends TypeSafeMatcher<String> {
+
+        private final String expected;
+
+        private final int amount;
+
+        StringContainsNumberMatcher(String expected, int amount) {
+            this.expected = expected;
+            this.amount = amount;
+        }
+
+        @Override
+        public boolean matchesSafely(String text) {
+            int lastIndex = 0;
+            int count = 0;
+            while (lastIndex != -1) {
+                lastIndex = text.indexOf(expected, lastIndex);
+                if (lastIndex != -1) {
+                    count++;
+                    lastIndex += expected.length();
+                }
+            }
+            return count == amount;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("containing '" + expected + "' exactly " + amount + " times");
+        }
+
+    }
+
+    private InvocationBuilder buildSimpleMethod() {
+        return new InvocationBuilder().mock(mock).simpleMethod();
+    }
+}
diff --git a/src/test/java/org/mockito/junit/TestableJUnitRunner.java b/src/test/java/org/mockito/junit/TestableJUnitRunner.java
new file mode 100644
index 0000000..c7b2440
--- /dev/null
+++ b/src/test/java/org/mockito/junit/TestableJUnitRunner.java
@@ -0,0 +1,32 @@
+package org.mockito.junit;
+
+import org.junit.runners.model.InitializationError;
+import org.mockito.internal.junit.MismatchReportingTestListener;
+import org.mockito.internal.junit.MockitoTestListener;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.StrictRunner;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockito.internal.util.Supplier;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class TestableJUnitRunner extends MockitoJUnitRunner {
+
+    private final static ThreadLocal<SimpleMockitoLogger> LOGGER = new ThreadLocal<SimpleMockitoLogger>() {
+        protected SimpleMockitoLogger initialValue() {
+            return new SimpleMockitoLogger();
+        }
+    };
+
+    public TestableJUnitRunner(Class<?> klass) throws InvocationTargetException, InitializationError {
+        super(new StrictRunner(new RunnerFactory().create(klass, new Supplier<MockitoTestListener>() {
+            public MockitoTestListener get() {
+                return new MismatchReportingTestListener(LOGGER.get());
+            }
+        }), klass));
+    }
+
+    public static SimpleMockitoLogger refreshedLogger() {
+        return LOGGER.get().clear();
+    }
+}
diff --git a/src/test/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunnerTest.java b/src/test/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunnerTest.java
new file mode 100644
index 0000000..8877e15
--- /dev/null
+++ b/src/test/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunnerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.runners;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.InitializationError;
+import org.mockito.internal.runners.InternalRunner;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class ConsoleSpammingMockitoJUnitRunnerTest extends TestBase {
+
+    private ConsoleSpammingMockitoJUnitRunner runner;
+
+    private MockitoLoggerStub loggerStub;
+
+    private RunNotifier notifier;
+
+    @Before
+    public void setup() throws InitializationError {
+        loggerStub = new MockitoLoggerStub();
+        notifier = new RunNotifier();
+    }
+
+    //TODO add sensible tests
+
+    @Test
+    public void shouldDelegateToGetDescription() throws Exception {
+        //given
+        final Description expectedDescription = Description.createSuiteDescription(this.getClass());
+        runner = new ConsoleSpammingMockitoJUnitRunner(loggerStub, new InternalRunnerStub() {
+            public Description getDescription() {
+                return expectedDescription;
+            }
+        });
+
+        //when
+        Description description = runner.getDescription();
+
+        //then
+        assertEquals(expectedDescription, description);
+    }
+
+    public class MockitoLoggerStub extends ConsoleMockitoLogger {
+
+        StringBuilder loggedInfo = new StringBuilder();
+
+        public void log(Object what) {
+            super.log(what);
+            loggedInfo.append(what);
+        }
+
+        public String getLoggedInfo() {
+            return loggedInfo.toString();
+        }
+    }
+
+    static class InternalRunnerStub implements InternalRunner {
+
+        public Description getDescription() {
+            return null;
+        }
+
+        public void run(RunNotifier notifier) {
+        }
+
+        public void filter(Filter filter) throws NoTestsRemainException {
+        }
+
+    }
+}
diff --git a/src/test/java/org/mockito/verification/NegativeDurationTest.java b/src/test/java/org/mockito/verification/NegativeDurationTest.java
new file mode 100644
index 0000000..fbb2480
--- /dev/null
+++ b/src/test/java/org/mockito/verification/NegativeDurationTest.java
@@ -0,0 +1,29 @@
+package org.mockito.verification;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.misusing.FriendlyReminderException;
+
+public class NegativeDurationTest {
+
+    @Test
+    public void should_throw_exception_when_duration_is_negative_for_timeout_method() {
+        try {
+            Mockito.timeout(-1);
+            Assert.fail("It is forbidden to invoke Mockito.timeout() with negative value.");
+        } catch (FriendlyReminderException e) {
+            Assert.assertTrue(true);
+        }
+    }
+
+    @Test
+    public void should_throw_exception_when_duration_is_negative_for_after_method() {
+        try {
+            Mockito.after(-1);
+            Assert.fail("It is forbidden to invoke Mockito.after() with negative value.");
+        } catch (FriendlyReminderException e) {
+            Assert.assertTrue(true);
+        }
+    }
+}
diff --git a/src/test/java/org/mockito/verification/TimeoutTest.java b/src/test/java/org/mockito/verification/TimeoutTest.java
new file mode 100644
index 0000000..1815c50
--- /dev/null
+++ b/src/test/java/org/mockito/verification/TimeoutTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.verification;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.util.Timer;
+import org.mockito.internal.verification.VerificationDataImpl;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class TimeoutTest extends TestBase {
+
+    @Mock
+    VerificationMode mode;
+    @Mock
+    VerificationDataImpl data;
+    @Mock
+    Timer timer;
+
+    private final MockitoAssertionError error = new MockitoAssertionError("");
+
+    @Test
+    public void should_pass_when_verification_passes() {
+        Timeout t = new Timeout(1, mode, timer);
+
+        when(timer.isCounting()).thenReturn(true);
+        doNothing().when(mode).verify(data);
+
+        t.verify(data);
+
+        InOrder inOrder = inOrder(timer);
+        inOrder.verify(timer).start();
+        inOrder.verify(timer).isCounting();
+    }
+
+    @Test
+    public void should_fail_because_verification_fails() {
+        Timeout t = new Timeout(1, mode, timer);
+
+        when(timer.isCounting()).thenReturn(true, true, true, false);
+        doThrow(error).
+        doThrow(error).
+        doThrow(error).
+        when(mode).verify(data);
+
+        try {
+            t.verify(data);
+            fail();
+        } catch (MockitoAssertionError e) {}
+
+        verify(timer, times(4)).isCounting();
+    }
+
+    @Test
+    public void should_pass_even_if_first_verification_fails() {
+        Timeout t = new Timeout(1, mode, timer);
+
+        when(timer.isCounting()).thenReturn(true, true, true, false);
+        doThrow(error).
+        doThrow(error).
+        doNothing().
+        when(mode).verify(data);
+
+        t.verify(data);
+        verify(timer, times(3)).isCounting();
+    }
+
+    @Test
+    public void should_try_to_verify_correct_number_of_times() {
+        Timeout t = new Timeout(10, mode, timer);
+
+        doThrow(error).when(mode).verify(data);
+        when(timer.isCounting()).thenReturn(true, true, true, true, true, false);
+
+        try {
+            t.verify(data);
+            fail();
+        } catch (MockitoAssertionError e) {}
+
+        verify(mode, times(5)).verify(data);
+    }
+
+}
diff --git a/src/test/java/org/mockitointegration/NoJUnitDependenciesTest.java b/src/test/java/org/mockitointegration/NoJUnitDependenciesTest.java
new file mode 100644
index 0000000..d39fa14
--- /dev/null
+++ b/src/test/java/org/mockitointegration/NoJUnitDependenciesTest.java
@@ -0,0 +1,55 @@
+package org.mockitointegration;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.agent.ByteBuddyAgent;
+import org.hamcrest.Matcher;
+import org.junit.Assume;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockitoutil.ClassLoaders;
+import org.objenesis.Objenesis;
+
+import java.util.Arrays;
+import java.util.Set;
+
+import static org.mockitoutil.ClassLoaders.coverageTool;
+
+public class NoJUnitDependenciesTest {
+
+    @Test
+    public void pure_mockito_should_not_depend_JUnit___ByteBuddy() throws Exception {
+        Assume.assumeTrue("ByteBuddyMockMaker".equals(Plugins.getMockMaker().getClass().getSimpleName()));
+
+        ClassLoader classLoader_without_JUnit = ClassLoaders.excludingClassLoader()
+                .withCodeSourceUrlOf(
+                        Mockito.class,
+                        Matcher.class,
+                        ByteBuddy.class,
+                        ByteBuddyAgent.class,
+                        Objenesis.class
+                )
+                .withCodeSourceUrlOf(coverageTool())
+                .without("junit", "org.junit")
+                .build();
+
+        Set<String> pureMockitoAPIClasses = ClassLoaders.in(classLoader_without_JUnit).omit("runners", "junit", "JUnit").listOwnedClasses();
+
+        // The later class is required to be initialized before any inline mock maker classes can be loaded.
+        checkDependency(classLoader_without_JUnit, "org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker");
+        pureMockitoAPIClasses.remove("org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker");
+
+        for (String pureMockitoAPIClass : pureMockitoAPIClasses) {
+            checkDependency(classLoader_without_JUnit, pureMockitoAPIClass);
+        }
+    }
+
+    private void checkDependency(ClassLoader classLoader_without_JUnit, String pureMockitoAPIClass) throws ClassNotFoundException {
+        try {
+            Class.forName(pureMockitoAPIClass, true, classLoader_without_JUnit);
+        } catch (Throwable e) {
+            e.printStackTrace();
+            throw new AssertionError(String.format("'%s' has some dependency to JUnit", pureMockitoAPIClass));
+        }
+    }
+}
diff --git a/src/test/java/org/mockitointegration/package-info.java b/src/test/java/org/mockitointegration/package-info.java
new file mode 100644
index 0000000..0699f8a
--- /dev/null
+++ b/src/test/java/org/mockitointegration/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Unit tests of mockito, also there's stack trace filtering)
+ *
+ * {@link org.mockitousage} is for functional / acceptance tests
+ */
+package org.mockitointegration;
diff --git a/src/test/java/org/mockitousage/CompilationWarningsTest.java b/src/test/java/org/mockitousage/CompilationWarningsTest.java
new file mode 100644
index 0000000..61214fd
--- /dev/null
+++ b/src/test/java/org/mockitousage/CompilationWarningsTest.java
@@ -0,0 +1,108 @@
+package org.mockitousage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import static org.mockito.BDDMockito.*;
+
+
+public class CompilationWarningsTest {
+
+    @Before
+    public void pay_attention_to_compilation_warnings_and_JDK_version() {
+    }
+
+    @Test
+    public void no_warnings_for_most_common_api() throws Exception {
+        doReturn(null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doReturn("a", 12).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doReturn(1000).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doThrow(new NullPointerException()).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doThrow(new NullPointerException(), new IllegalArgumentException()).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doThrow(NullPointerException.class).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+
+        doAnswer(ignore()).doReturn(null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doAnswer(ignore()).doReturn("a", 12).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doAnswer(ignore()).doReturn(1000).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doAnswer(ignore()).doThrow(new NullPointerException()).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doAnswer(ignore()).doThrow(new NullPointerException(), new IllegalArgumentException()).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doAnswer(ignore()).doThrow(NullPointerException.class).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn(null);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn("a", 12L);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn(1000);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenThrow(new NullPointerException());
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenThrow(new NullPointerException(), new IllegalArgumentException());
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenThrow(NullPointerException.class);
+
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenReturn(null);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenReturn("a", 12L);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenReturn(1000);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenThrow(new NullPointerException());
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenThrow(new NullPointerException(), new IllegalArgumentException());
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenThrow(NullPointerException.class);
+
+        willReturn(null).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willReturn("a", 12).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willReturn(1000).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willThrow(new NullPointerException()).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willThrow(new NullPointerException(), new IllegalArgumentException()).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willThrow(NullPointerException.class).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+
+        willAnswer(ignore()).willReturn(null).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willAnswer(ignore()).willReturn("a", 12).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willAnswer(ignore()).willReturn(1000).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willAnswer(ignore()).willThrow(new NullPointerException()).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willAnswer(ignore()).willThrow(new NullPointerException(), new IllegalArgumentException()).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        willAnswer(ignore()).willThrow(NullPointerException.class).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn(null);
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn("a", 12L);
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn(1000);
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willThrow(new NullPointerException());
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willThrow(new NullPointerException(), new IllegalArgumentException());
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willThrow(NullPointerException.class);
+
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willReturn(null);
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willReturn("a", 12L);
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willReturn(1000);
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willThrow(new NullPointerException());
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willThrow(new NullPointerException(), new IllegalArgumentException());
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willThrow(NullPointerException.class);
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void heap_pollution_JDK7plus_warning_avoided_BUT_now_unchecked_generic_array_creation_warnings_ON_JDK5plus_environment() throws Exception {
+        doThrow(NullPointerException.class, IllegalArgumentException.class).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenThrow(NullPointerException.class, IllegalArgumentException.class);
+        doAnswer(ignore()).doThrow(NullPointerException.class, IllegalArgumentException.class).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+
+        willThrow(NullPointerException.class, IllegalArgumentException.class).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willThrow(NullPointerException.class, IllegalArgumentException.class);
+        willAnswer(ignore()).willThrow(NullPointerException.class, IllegalArgumentException.class).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+    }
+
+    @Test
+    public void unchecked_confusing_null_argument_warnings() throws Exception {
+        doReturn(null, (Object[]) null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        doAnswer(ignore()).doReturn(null, (Object[]) null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn(null, (Object[]) null);
+        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenReturn(null, (Object[]) null);
+        willReturn(null, (Object[]) null).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn(null, (Object[]) null);
+        willAnswer(ignore()).willReturn(null, (Object[]) null).given(mock(IMethods.class)).objectReturningMethodNoArgs();
+        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willReturn(null, (Object[]) null);
+    }
+
+    private static Answer<?> ignore() {
+        return new Answer<Object>() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                return null;
+            }
+        };
+    }
+}
diff --git a/src/test/java/org/mockitousage/IMethods.java b/src/test/java/org/mockitousage/IMethods.java
new file mode 100644
index 0000000..2d56631
--- /dev/null
+++ b/src/test/java/org/mockitousage/IMethods.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage;
+
+import java.io.IOException;
+import java.nio.charset.CharacterCodingException;
+import java.util.*;
+
+public interface IMethods {
+
+    boolean booleanReturningMethod();
+
+    Boolean booleanObjectReturningMethod();
+
+    byte byteReturningMethod();
+
+    Byte byteObjectReturningMethod();
+
+    short shortReturningMethod();
+
+    Short shortObjectReturningMethod();
+
+    char charReturningMethod();
+
+    Character charObjectReturningMethod();
+
+    int intReturningMethod();
+
+    Integer integerReturningMethod();
+
+    long longReturningMethod();
+
+    Long longObjectReturningMethod();
+
+    float floatReturningMethod();
+
+    Float floatObjectReturningMethod();
+
+    double doubleReturningMethod();
+
+    Double doubleObjectReturningMethod();
+
+    Object objectReturningMethod(Object ... objects);
+
+    Object objectReturningMethodNoArgs();
+
+    String oneArg(boolean value);
+
+    String oneArg(Boolean value);
+
+    String forBoolean(Boolean value);
+
+    String oneArg(byte value);
+
+    String oneArg(Byte value);
+
+    String forByte(Byte value);
+
+    String oneArg(short value);
+
+    String oneArg(Short value);
+
+    String forShort(Short value);
+
+    String oneArg(char value);
+
+    String oneArg(Character value);
+
+    String forCharacter(Character value);
+
+    String oneArg(int value);
+
+    String oneArg(Integer value);
+
+    String forInteger(Integer value);
+
+    String oneArg(long value);
+
+    String oneArg(Long value);
+
+    String forLong(Long value);
+
+    String oneArg(float value);
+
+    String oneArg(Float value);
+
+    String forFloat(Float value);
+
+    String oneArg(double value);
+
+    String oneArg(Double value);
+
+    String forDouble(Double value);
+
+    String oneArg(Object value);
+
+    String oneArg(String value);
+
+    String throwsNothing(boolean value);
+
+    String throwsIOException(int count) throws IOException;
+
+    String throwsError(int count);
+
+    String simpleMethod();
+
+    String differentMethod();
+
+    String differentMethod(String argument);
+
+    String otherMethod();
+
+    String simpleMethod(String argument);
+
+    String simpleMethod(Collection<?> collection);
+
+    String simpleMethod(Object argument);
+
+    String simpleMethod(int argument);
+
+    String simpleMethod(String argOne, Integer argTwo);
+
+    String simpleMethod(String one, Integer two, Integer three, Integer four, Integer five);
+
+    String simpleMethod(String one, String[] two);
+
+    Object threeArgumentMethod(int valueOne, Object valueTwo, String valueThree);
+
+    String threeArgumentMethodWithStrings(int valueOne, String valueTwo, String valueThree);
+
+    String fourArgumentMethod(int valueOne, String valueTwo, String valueThree, boolean[] array);
+
+    void twoArgumentMethod(int one, int two);
+
+    void arrayMethod(String[] strings);
+
+    String oneArray(boolean[] array);
+
+    String oneArray(byte[] array);
+
+    String oneArray(char[] array);
+
+    String oneArray(double[] array);
+
+    String oneArray(float[] array);
+
+    String oneArray(int[] array);
+
+    String oneArray(long[] array);
+
+    String oneArray(short[] array);
+
+    String oneArray(Object[] array);
+
+    String canThrowException() throws CharacterCodingException;
+
+    String oneArray(String[] array);
+
+    void varargsString(int i, String... string);
+
+    Object varargsObject(int i, Object... object);
+
+    void varargsbyte(byte... bytes);
+
+    int varargs(Object ... object);
+
+    String varargsReturningString(Object ... object);
+
+    int varargs(String ... string);
+
+    void mixedVarargs(Object i, String ... string);
+
+    String mixedVarargsReturningString(Object i, String ... string);
+
+    String[] mixedVarargsReturningStringArray(Object i, String ... string);
+
+    Object[] mixedVarargsReturningObjectArray(Object i, String ... string);
+
+    List<String> listReturningMethod(Object ... objects);
+
+    LinkedList<String> linkedListReturningMethod();
+
+    String toString();
+
+    String toString(String foo);
+
+    void voidMethod();
+
+    Void voidReturningMethod();
+
+    String forList(List<String> list);
+
+    String forSet(Set<String> anySet);
+
+    String forMap(Map<String, String> map);
+
+    String forCollection(Collection<String> collection);
+
+    String forIterable(Iterable<String> iterable);
+
+    Object[] arrayReturningMethod();
+
+    IMethods iMethodsReturningMethod();
+
+    String stringReturningMethod();
+
+    Object objectArgMethod(Object str);
+
+    Object listArgMethod(List<String> list);
+
+    Object collectionArgMethod(Collection<String> collection);
+
+    Object iterableArgMethod(Iterable<String> collection);
+
+    Object setArgMethod(Set<String> set);
+
+    void longArg(long longArg);
+
+    void intArgumentMethod(int i);
+
+    int intArgumentReturningInt(int i);
+
+    boolean equals(String str);
+
+    boolean equals();
+
+    int hashCode(String str);
+
+    int toIntPrimitive(Integer i);
+
+    Integer toIntWrapper(int i);
+
+    String forObject(Object object);
+}
diff --git a/src/test/java/org/mockitousage/MethodsImpl.java b/src/test/java/org/mockitousage/MethodsImpl.java
new file mode 100644
index 0000000..b983057
--- /dev/null
+++ b/src/test/java/org/mockitousage/MethodsImpl.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage;
+
+import java.io.IOException;
+import java.nio.charset.CharacterCodingException;
+import java.util.*;
+
+public class MethodsImpl implements IMethods {
+    public boolean booleanReturningMethod() {
+        return false;
+    }
+
+    public Boolean booleanObjectReturningMethod() {
+        return null;
+    }
+
+    public byte byteReturningMethod() {
+        return 0;
+    }
+
+    public Byte byteObjectReturningMethod() {
+        return null;
+    }
+
+    public short shortReturningMethod() {
+        return 0;
+    }
+
+    public Short shortObjectReturningMethod() {
+        return null;
+    }
+
+    public char charReturningMethod() {
+        return 0;
+    }
+
+    public Character charObjectReturningMethod() {
+        return null;
+    }
+
+    public int intReturningMethod() {
+        return 0;
+    }
+
+    public Integer integerReturningMethod() {
+        return null;
+    }
+
+    public long longReturningMethod() {
+        return 0;
+    }
+
+    public Long longObjectReturningMethod() {
+        return null;
+    }
+
+    public float floatReturningMethod() {
+        return 0;
+    }
+
+    public Float floatObjectReturningMethod() {
+        return null;
+    }
+
+    public double doubleReturningMethod() {
+        return 0;
+    }
+
+    public Double doubleObjectReturningMethod() {
+        return null;
+    }
+
+    public Object objectReturningMethod(Object... objects) {
+        return null;
+    }
+
+    public Object objectReturningMethodNoArgs() {
+        return null;
+    }
+
+    public String oneArg(boolean value) {
+        return null;
+    }
+
+    public String oneArg(Boolean value) {
+        return null;
+    }
+
+    public String forBoolean(Boolean value) {
+        return null;
+    }
+
+    public String oneArg(byte value) {
+        return null;
+    }
+
+    public String oneArg(Byte value) {
+        return null;
+    }
+
+    public String forByte(Byte value) {
+        return null;
+    }
+
+    public String oneArg(short value) {
+        return null;
+    }
+
+    public String oneArg(Short value) {
+        return null;
+    }
+
+    public String forShort(Short value) {
+        return null;
+    }
+
+    public String oneArg(char value) {
+        return null;
+    }
+
+    public String oneArg(Character value) {
+        return null;
+    }
+
+    public String forCharacter(Character value) {
+        return null;
+    }
+
+    public String oneArg(int value) {
+        return null;
+    }
+
+    public String oneArg(Integer value) {
+        return null;
+    }
+
+    public String forInteger(Integer value) {
+        return null;
+    }
+
+    public String oneArg(long value) {
+        return null;
+    }
+
+    public String oneArg(Long value) {
+        return null;
+    }
+
+    public String forLong(Long value) {
+        return null;
+    }
+
+    public String oneArg(float value) {
+        return null;
+    }
+
+    public String oneArg(Float value) {
+        return null;
+    }
+
+    public String forFloat(Float value) {
+        return null;
+    }
+
+    public String oneArg(double value) {
+        return null;
+    }
+
+    public String oneArg(Double value) {
+        return null;
+    }
+
+    public String forDouble(Double value) {
+        return null;
+    }
+
+    public String oneArg(Object value) {
+        return null;
+    }
+
+    public String oneArg(String value) {
+        return null;
+    }
+
+    public String throwsNothing(boolean value) {
+        return null;
+    }
+
+    public String throwsIOException(int count) throws IOException {
+        return null;
+    }
+
+    public String throwsError(int count) {
+        return null;
+    }
+
+    public String simpleMethod() {
+        return null;
+    }
+
+    public String differentMethod() {
+        return null;
+    }
+
+    public String differentMethod(String argument) {
+        return null;
+    }
+
+    public String otherMethod() {
+        return null;
+    }
+
+    public String simpleMethod(String argument) {
+        return null;
+    }
+
+    public String simpleMethod(Collection<?> collection) {
+        return null;
+    }
+
+    public String simpleMethod(Object argument) {
+        return null;
+    }
+
+    public String simpleMethod(int argument) {
+        return null;
+    }
+
+    public String simpleMethod(String argOne, Integer argTwo) {
+        return null;
+    }
+
+    public String simpleMethod(String one, Integer two, Integer three, Integer four, Integer five) {
+        return null;
+    }
+
+    public String simpleMethod(String one, String[] two) {
+        return null;
+    }
+
+    public Object threeArgumentMethod(int valueOne, Object valueTwo, String valueThree) {
+        return null;
+    }
+
+    public String threeArgumentMethodWithStrings(int valueOne, String valueTwo, String valueThree) {
+        return null;
+    }
+
+    public String fourArgumentMethod(int valueOne, String valueTwo, String valueThree, boolean[] array) {
+        return null;
+    }
+
+    public void twoArgumentMethod(int one, int two) {
+
+    }
+
+    public void arrayMethod(String[] strings) {
+
+    }
+
+    public String oneArray(boolean[] array) {
+        return null;
+    }
+
+    public String oneArray(byte[] array) {
+        return null;
+    }
+
+    public String oneArray(char[] array) {
+        return null;
+    }
+
+    public String oneArray(double[] array) {
+        return null;
+    }
+
+    public String oneArray(float[] array) {
+        return null;
+    }
+
+    public String oneArray(int[] array) {
+        return null;
+    }
+
+    public String oneArray(long[] array) {
+        return null;
+    }
+
+    public String oneArray(short[] array) {
+        return null;
+    }
+
+    public String oneArray(Object[] array) {
+        return null;
+    }
+
+    public String canThrowException() throws CharacterCodingException {
+        return null;
+    }
+
+    public String oneArray(String[] array) {
+        return null;
+    }
+
+    public void varargsString(int i, String... string) {
+
+    }
+
+    public Object varargsObject(int i, Object... object) {
+        return null;
+    }
+
+    public int varargs(Object... object) {
+        return -1;
+    }
+
+    public String varargsReturningString(Object... object) {
+        return null;
+    }
+
+    public int varargs(String... string) {
+        return -1;
+    }
+
+    public void mixedVarargs(Object i, String... string) {
+    }
+
+    public String mixedVarargsReturningString(Object i, String... string) {
+        return null;
+    }
+
+    public String[] mixedVarargsReturningStringArray(Object i, String... string) {
+        return null;
+    }
+
+    public Object[] mixedVarargsReturningObjectArray(Object i, String... string) {
+        return null;
+    }
+
+    public void varargsbyte(byte... bytes) {
+    }
+
+    public List<String> listReturningMethod(Object... objects) {
+        return null;
+    }
+
+    public LinkedList<String> linkedListReturningMethod() {
+        return null;
+    }
+
+    public String toString(String foo) {
+        return null;
+    }
+
+    public void voidMethod() {
+
+    }
+
+    public String forList(List<String> list) {
+        return null;
+    }
+
+    public String forSet(Set<String> anySet) {
+        return null;
+    }
+
+    public String forMap(Map<String, String> map) {
+        return null;
+    }
+
+    public String forCollection(Collection<String> collection) {
+        return null;
+    }
+
+    public String forIterable(Iterable<String> iterable) {
+        return null;
+    }
+
+    public Object[] arrayReturningMethod() {
+        return new Object[0];
+    }
+
+    public IMethods iMethodsReturningMethod() {
+        return null;
+    }
+
+    public String stringReturningMethod() {
+        return null;
+    }
+
+    public Object objectArgMethod(Object str) {
+        return null;
+    }
+
+    public Object listArgMethod(List<String> list) {
+        return null;
+    }
+
+    public Object collectionArgMethod(Collection<String> collection) {
+        return null;
+    }
+
+    public Object iterableArgMethod(Iterable<String> iterable) {
+        return null;
+    }
+
+    public Object setArgMethod(Set<String> set) {
+        return null;
+    }
+
+    public void longArg(long longArg) {
+
+    }
+
+    public void intArgumentMethod(int i) {
+
+    }
+
+    public int intArgumentReturningInt(int i) {
+        return 0;
+    }
+
+    public boolean equals(String str) {
+        return false;
+    }
+
+    public boolean equals() {
+        return false;
+    }
+
+    public int hashCode(String str) {
+        return 0;
+    }
+
+    public int toIntPrimitive(Integer i) {
+        return 0;
+    }
+
+    public Integer toIntWrapper(int i) {
+        return null;
+    }
+
+    public String forObject(Object object) {
+        return null;
+    }
+
+    @Override
+    public Void voidReturningMethod() {
+        return null;
+    }
+}
diff --git a/src/test/java/org/mockitousage/PlaygroundTest.java b/src/test/java/org/mockitousage/PlaygroundTest.java
new file mode 100644
index 0000000..d3f5777
--- /dev/null
+++ b/src/test/java/org/mockitousage/PlaygroundTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+public class PlaygroundTest extends TestBase {
+    static class Foo {
+
+        int doSomeThing() {
+            return 0;
+        }
+
+        protected String getStuff() {
+            return "foo";
+        }
+    }
+
+    class Boo {
+        final public Object withLong(long y) {
+                         return "";
+        }
+
+        public Object foo() {
+                   return "";
+        }
+    }
+
+    Foo mock;
+    @Mock IMethods mockTwo;
+
+    @Test
+    public void spyInAction() {
+
+    }
+
+    @Test
+    public void partialMockInAction() {
+//        mock = mock(Foo.class, withSettings()
+//            .defaultBehavior(CALLS_REAL_METHODS);
+
+//        mock = mock(Foo.class, withSettings()
+//            .defaultMockAnswer(CALLS_REAL_METHODS);
+
+//        mock = mock(Foo.class, withSettings()
+//            .defaultAnswer(CALLS_REAL_METHODS);
+
+//        mock = mock(Foo.class, CALLS_REAL_METHODS);
+
+//        mock = mock(Foo.class, withSettings()
+//            .defaultBehavior(CALLS_REAL_METHODS)
+//            .createUsingDefaultConstructor();
+//
+//        mock = mock(Foo.class, withSettings()
+//            .defaultBehavior(CALLS_REAL_METHODS)
+//            .createPassingArguments("some arg", 1);
+//
+//        spy = spy(Foo.class, "some arg", 1);
+//
+//            .withName("foo")
+//            .withDefaultBehavior(RETURNS_SMART_NULLS)
+//            .withInterfaces(Bar.class);
+//
+//        mock = mock(Foo.class)
+//            .name("foo")
+//            .defaultBehavior(RETURNS_SMART_NULLS)
+//            .interfaces(Bar.class);
+//
+//        mock = mock(Foo.class)
+//            .named("foo")
+//            .byDefault(RETURNS_SMART_NULLS)
+//            .alsoImplements(Bar.class, Bar2.class);
+//
+//        mock = mock(Foo.class)
+//            hasName("foo");
+
+//        when(mock.getStuff()).thenReturn("aha!");
+//        when(mock.doSomeThing()).thenCallRealMethod();
+//
+
+//        mock.doSomeThing();
+    }
+
+//    interface Colored {
+//
+//    }
+//
+//    interface Bar {
+//        <T extends Foo & Colored> T getColoredPoint();
+//    }
+//
+//    @Test
+//    public void testname() throws Exception {
+//        when(mock.get()).then(returnArgument());
+//
+//        Bar mock = mock(Bar.class);
+//        when(mock.getColoredPoint()).thenReturn(new Foo());
+//    }
+}
diff --git a/src/test/java/org/mockitousage/PlaygroundWithDemoOfUnclonedParametersProblemTest.java b/src/test/java/org/mockitousage/PlaygroundWithDemoOfUnclonedParametersProblemTest.java
new file mode 100644
index 0000000..f225df8
--- /dev/null
+++ b/src/test/java/org/mockitousage/PlaygroundWithDemoOfUnclonedParametersProblemTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitoutil.TestBase;
+
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.willAnswer;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+
+public class PlaygroundWithDemoOfUnclonedParametersProblemTest extends TestBase {
+
+    ImportManager importManager;
+    ImportLogDao importLogDao;
+    IImportHandler importHandler;
+
+    @Before
+    public void setUp() throws Exception {
+        importLogDao = Mockito.mock(ImportLogDao.class);
+        importHandler = Mockito.mock(IImportHandler.class);
+        importManager = new ImportManager(importLogDao);
+    }
+
+    @Test
+    public void shouldIncludeInitialLog() {
+        //given
+        int importType = 0;
+        Date currentDate = new GregorianCalendar(2009, 10, 12).getTime();
+
+        ImportLogBean initialLog = new ImportLogBean(currentDate, importType);
+        initialLog.setStatus(1);
+
+        given(importLogDao.anyImportRunningOrRunnedToday(importType, currentDate)).willReturn(false);
+        willAnswer(byCheckingLogEquals(initialLog)).given(importLogDao).include(any(ImportLogBean.class));
+
+        //when
+        importManager.startImportProcess(importType, currentDate);
+
+        //then
+        verify(importLogDao).include(any(ImportLogBean.class));
+    }
+
+    @Test
+    public void shouldAlterFinalLog() {
+        //given
+        int importType = 0;
+        Date currentDate = new GregorianCalendar(2009, 10, 12).getTime();
+
+        ImportLogBean finalLog = new ImportLogBean(currentDate, importType);
+        finalLog.setStatus(9);
+
+        given(importLogDao.anyImportRunningOrRunnedToday(importType, currentDate)).willReturn(false);
+        willAnswer(byCheckingLogEquals(finalLog)).given(importLogDao).alter(any(ImportLogBean.class));
+
+        //when
+        importManager.startImportProcess(importType, currentDate);
+
+        //then
+        verify(importLogDao).alter(any(ImportLogBean.class));
+    }
+
+    private Answer<Object> byCheckingLogEquals(final ImportLogBean status) {
+        return new Answer<Object>() {
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                ImportLogBean bean =  invocation.getArgument(0);
+                assertEquals(status, bean);
+                return null;
+            }
+        };
+    }
+
+    public class ImportManager {
+
+        public ImportManager(ImportLogDao pImportLogDao) {
+            super();
+            importLogDao = pImportLogDao;
+        }
+
+        private ImportLogDao importLogDao = null;
+
+        public void startImportProcess(int importType, Date date) {
+            ImportLogBean importLogBean = null;
+
+            try {
+                importLogBean = createResume(importType, date);
+                if (isOkToImport(importType, date)) {
+                    // get the right handler
+                    //importLogBean = ImportHandlerFactory.singleton().getImportHandler(importType).processImport(importLogBean);
+                    // 2 = ok
+                    importLogBean.setStatus(2);
+                } else {
+                    // 5 = failed - is there a running process
+                    importLogBean.setStatus(9);
+                }
+            } catch (Exception e) {
+                // 9 = failed - exception
+                if (importLogBean != null)
+                    importLogBean.setStatus(9);
+            } finally {
+                if (importLogBean != null)
+                    finalizeResume(importLogBean);
+            }
+        }
+
+        private boolean isOkToImport(int importType, Date date) {
+            return importLogDao.anyImportRunningOrRunnedToday(importType, date);
+        }
+
+        private ImportLogBean createResume(int importType, Date date) {
+            ImportLogBean importLogBean = new ImportLogBean(date,
+                    importType);
+            // 1 = running
+            importLogBean.setStatus(1);
+            importLogDao.include(importLogBean);
+            return importLogBean;
+        }
+
+        private void finalizeResume(ImportLogBean importLogBean) {
+            importLogDao.alter(importLogBean);
+        }
+    }
+
+    private interface ImportLogDao {
+        boolean anyImportRunningOrRunnedToday(int importType, Date currentDate);
+
+        void include(ImportLogBean importLogBean);
+
+        void alter(ImportLogBean importLogBean);
+    }
+
+    private class IImportHandler {
+    }
+
+    private class ImportLogBean {
+        private Date currentDate;
+        private int importType;
+        private int status;
+
+        public ImportLogBean(Date currentDate, int importType) {
+            this.currentDate = currentDate;
+            this.importType = importType;
+        }
+
+        public void setStatus(int status) {
+            this.status = status;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof ImportLogBean)) return false;
+
+            ImportLogBean that = (ImportLogBean) o;
+
+            if (importType != that.importType) return false;
+            if (status != that.status) return false;
+            if (currentDate != null ? !currentDate.equals(that.currentDate) : that.currentDate != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = currentDate != null ? currentDate.hashCode() : 0;
+            result = 31 * result + importType;
+            result = 31 * result + status;
+            return result;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/AnnotationsTest.java b/src/test/java/org/mockitousage/annotation/AnnotationsTest.java
new file mode 100644
index 0000000..9d93198
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/AnnotationsTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.verify;
+
+public class AnnotationsTest extends TestBase {
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface NotAMock {}
+
+    @Mock List<?> list;
+    @Mock final Map<Integer, String> map = new HashMap<Integer, String>();
+
+    @NotAMock Set<?> notAMock;
+
+    @Mock List<?> listTwo;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void shouldInitMocks() throws Exception {
+        list.clear();
+        map.clear();
+        listTwo.clear();
+
+        verify(list).clear();
+        verify(map).clear();
+        verify(listTwo).clear();
+    }
+
+    @Test
+    public void shouldScreamWhenInitializingMocksForNullClass() throws Exception {
+        try {
+            MockitoAnnotations.initMocks(null);
+            fail();
+        } catch (MockitoException e) {
+            assertEquals("testClass cannot be null. For info how to use @Mock annotations see examples in javadoc for MockitoAnnotations class",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldLookForAnnotatedMocksInSuperClasses() throws Exception {
+        Sub sub = new Sub();
+        MockitoAnnotations.initMocks(sub);
+
+        assertNotNull(sub.getMock());
+        assertNotNull(sub.getBaseMock());
+        assertNotNull(sub.getSuperBaseMock());
+    }
+
+    @Mock(answer = Answers.RETURNS_MOCKS, name = "i have a name") IMethods namedAndReturningMocks;
+    @Mock(answer = Answers.RETURNS_DEFAULTS) IMethods returningDefaults;
+    @Mock(extraInterfaces = {List.class}) IMethods hasExtraInterfaces;
+    @Mock() IMethods noExtraConfig;
+
+    @Test
+    public void shouldInitMocksWithGivenSettings() throws Exception {
+        assertEquals("i have a name", namedAndReturningMocks.toString());
+        assertNotNull(namedAndReturningMocks.iMethodsReturningMethod());
+
+        assertEquals("returningDefaults", returningDefaults.toString());
+        assertEquals(0, returningDefaults.intReturningMethod());
+
+        assertTrue(hasExtraInterfaces instanceof List);
+
+        assertEquals(0, noExtraConfig.intReturningMethod());
+    }
+
+    class SuperBase {
+        @Mock private IMethods mock;
+
+        public IMethods getSuperBaseMock() {
+            return mock;
+        }
+    }
+
+    class Base extends SuperBase {
+        @Mock private IMethods mock;
+
+        public IMethods getBaseMock() {
+            return mock;
+        }
+    }
+
+    class Sub extends Base {
+        @Mock private IMethods mock;
+
+        public IMethods getMock() {
+            return mock;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/CaptorAnnotationBasicTest.java b/src/test/java/org/mockitousage/annotation/CaptorAnnotationBasicTest.java
new file mode 100644
index 0000000..8314f9d
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/CaptorAnnotationBasicTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertSame;
+import static org.mockito.Mockito.verify;
+
+@SuppressWarnings("unchecked")
+public class CaptorAnnotationBasicTest extends TestBase {
+
+    public class Person {
+        private final String name;
+        private final String surname;
+
+        public Person(String name, String surname) {
+            this.name = name;
+            this.surname = surname;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getSurname() {
+            return surname;
+        }
+    }
+
+    public interface PeopleRepository {
+        void save(Person capture);
+    }
+
+    @Mock PeopleRepository peopleRepository;
+
+    private void createPerson(String name, String surname) {
+        peopleRepository.save(new Person(name, surname));
+    }
+
+    @Test
+    public void shouldUseCaptorInOrdinaryWay() {
+        //when
+        createPerson("Wes", "Williams");
+
+        //then
+        ArgumentCaptor<Person> captor = ArgumentCaptor.forClass(Person.class);
+        verify(peopleRepository).save(captor.capture());
+        assertEquals("Wes", captor.getValue().getName());
+        assertEquals("Williams", captor.getValue().getSurname());
+    }
+
+    @Captor ArgumentCaptor<Person> captor;
+
+    @Test
+    public void shouldUseAnnotatedCaptor() {
+        //when
+        createPerson("Wes", "Williams");
+
+        //then
+        verify(peopleRepository).save(captor.capture());
+        assertEquals("Wes", captor.getValue().getName());
+        assertEquals("Williams", captor.getValue().getSurname());
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Captor ArgumentCaptor genericLessCaptor;
+
+    @Test
+    public void shouldUseGenericlessAnnotatedCaptor() {
+        //when
+        createPerson("Wes", "Williams");
+
+        //then
+        verify(peopleRepository).save((Person) genericLessCaptor.capture());
+        assertEquals("Wes", ((Person) genericLessCaptor.getValue()).getName());
+        assertEquals("Williams", ((Person) genericLessCaptor.getValue()).getSurname());
+    }
+
+    @Captor ArgumentCaptor<List<String>> genericListCaptor;
+    @Mock IMethods mock;
+
+    @Test
+    public void shouldCaptureGenericList() {
+        //given
+        List<String> list = new LinkedList<String>();
+        mock.listArgMethod(list);
+
+        //when
+        verify(mock).listArgMethod(genericListCaptor.capture());
+
+        //then
+        assertSame(list, genericListCaptor.getValue());
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/CaptorAnnotationTest.java b/src/test/java/org/mockitousage/annotation/CaptorAnnotationTest.java
new file mode 100644
index 0000000..7a34a3c
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/CaptorAnnotationTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.Test;
+import org.mockito.*;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CaptorAnnotationTest extends TestBase {
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface NotAMock {
+    }
+
+    @Captor
+    final ArgumentCaptor<String> finalCaptor = ArgumentCaptor.forClass(String.class);
+
+    @Captor
+    ArgumentCaptor<List<List<String>>> genericsCaptor;
+
+    @SuppressWarnings("rawtypes")
+    @Captor
+    ArgumentCaptor nonGenericCaptorIsAllowed;
+
+    @Mock
+    MockInterface mockInterface;
+
+    @NotAMock
+    Set<?> notAMock;
+
+    public interface MockInterface {
+        void testMe(String simple, List<List<String>> genericList);
+    }
+
+    @Test
+    public void testNormalUsage() {
+
+        MockitoAnnotations.initMocks(this);
+
+        // check if assigned correctly
+        assertNotNull(finalCaptor);
+        assertNotNull(genericsCaptor);
+        assertNotNull(nonGenericCaptorIsAllowed);
+        assertNull(notAMock);
+
+        // use captors in the field to be sure they are cool
+        String argForFinalCaptor = "Hello";
+        ArrayList<List<String>> argForGenericsCaptor = new ArrayList<List<String>>();
+
+        mockInterface.testMe(argForFinalCaptor, argForGenericsCaptor);
+
+        Mockito.verify(mockInterface).testMe(finalCaptor.capture(), genericsCaptor.capture());
+
+        assertEquals(argForFinalCaptor, finalCaptor.getValue());
+        assertEquals(argForGenericsCaptor, genericsCaptor.getValue());
+
+    }
+
+    public static class WrongType {
+        @Captor
+        List<?> wrongType;
+    }
+
+    @Test
+    public void shouldScreamWhenWrongTypeForCaptor() {
+        try {
+            MockitoAnnotations.initMocks(new WrongType());
+            fail();
+        } catch (MockitoException e) {}
+    }
+
+    public static class ToManyAnnotations {
+        @Captor
+        @Mock
+        ArgumentCaptor<List> missingGenericsField;
+    }
+
+    @Test
+    public void shouldScreamWhenMoreThanOneMockitoAnnotaton() {
+        try {
+            MockitoAnnotations.initMocks(new ToManyAnnotations());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e)
+                .hasMessageContaining("missingGenericsField")
+                .hasMessageContaining("multiple Mockito annotations");
+        }
+    }
+
+    @Test
+    public void shouldScreamWhenInitializingCaptorsForNullClass() throws Exception {
+        try {
+            MockitoAnnotations.initMocks(null);
+            fail();
+        } catch (MockitoException e) {
+        }
+    }
+
+    @Test
+    public void shouldLookForAnnotatedCaptorsInSuperClasses() throws Exception {
+        Sub sub = new Sub();
+        MockitoAnnotations.initMocks(sub);
+
+        assertNotNull(sub.getCaptor());
+        assertNotNull(sub.getBaseCaptor());
+        assertNotNull(sub.getSuperBaseCaptor());
+    }
+
+    class SuperBase {
+        @Captor
+        private ArgumentCaptor<IMethods> mock;
+
+        public ArgumentCaptor<IMethods> getSuperBaseCaptor() {
+            return mock;
+        }
+    }
+
+    class Base extends SuperBase {
+        @Captor
+        private ArgumentCaptor<IMethods> mock;
+
+        public ArgumentCaptor<IMethods> getBaseCaptor() {
+            return mock;
+        }
+    }
+
+    class Sub extends Base {
+        @Captor
+        private ArgumentCaptor<IMethods> mock;
+
+        public ArgumentCaptor<IMethods> getCaptor() {
+            return mock;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/CaptorAnnotationUnhappyPathTest.java b/src/test/java/org/mockitousage/annotation/CaptorAnnotationUnhappyPathTest.java
new file mode 100644
index 0000000..b4a7574
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/CaptorAnnotationUnhappyPathTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Captor;
+import org.mockito.MockitoAnnotations;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CaptorAnnotationUnhappyPathTest extends TestBase {
+
+    @Captor List<?> notACaptorField;
+
+    @Before
+    @Override
+    public void init() {
+        //we need to get rid of parent implementation this time
+    }
+
+    @Test
+    public void shouldFailIfCaptorHasWrongType() throws Exception {
+        try {
+            //when
+            MockitoAnnotations.initMocks(this);
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e)
+                .hasMessageContaining("notACaptorField")
+                .hasMessageContaining("wrong type");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/DeprecatedAnnotationEngineApiTest.java b/src/test/java/org/mockitousage/annotation/DeprecatedAnnotationEngineApiTest.java
new file mode 100644
index 0000000..9ab6094
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/DeprecatedAnnotationEngineApiTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.configuration.DefaultMockitoConfiguration;
+import org.mockito.internal.configuration.ConfigurationAccess;
+import org.mockito.internal.configuration.IndependentAnnotationEngine;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+
+public class DeprecatedAnnotationEngineApiTest extends TestBase {
+
+    @After
+    public void goBackToDefaultConfiguration() {
+        ConfigurationAccess.getConfig().overrideAnnotationEngine(null);
+    }
+
+    class SimpleTestCase {
+        @InjectMocks Tested tested = new Tested();
+        @Mock Dependency mock;
+    }
+
+    class Tested {
+        Dependency dependency;
+        public void setDependency(Dependency dependency) {
+            this.dependency = dependency;
+        }
+    }
+
+    class Dependency {}
+
+    @Test
+    public void shouldInjectMocksIfThereIsNoUserDefinedEngine() throws Exception {
+        //given
+        AnnotationEngine defaultEngine = new DefaultMockitoConfiguration().getAnnotationEngine();
+        ConfigurationAccess.getConfig().overrideAnnotationEngine(defaultEngine);
+        SimpleTestCase test = new SimpleTestCase();
+
+        //when
+        MockitoAnnotations.initMocks(test);
+
+        //then
+        assertNotNull(test.mock);
+        assertNotNull(test.tested.dependency);
+        assertSame(test.mock, test.tested.dependency);
+    }
+
+    @Test
+    public void shouldRespectUsersEngine() throws Exception {
+        //given
+        AnnotationEngine customizedEngine = new IndependentAnnotationEngine() { /**/ };
+        ConfigurationAccess.getConfig().overrideAnnotationEngine(customizedEngine);
+        SimpleTestCase test = new SimpleTestCase();
+
+        //when
+        MockitoAnnotations.initMocks(test);
+
+        //then
+        assertNotNull(test.mock);
+        assertNull(test.tested.dependency);
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/InjectionOfInlinedMockDeclarationTest.java b/src/test/java/org/mockitousage/annotation/InjectionOfInlinedMockDeclarationTest.java
new file mode 100644
index 0000000..39ef5f3
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/InjectionOfInlinedMockDeclarationTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.annotation;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+@RunWith(MockitoJUnitRunner.class)
+public class InjectionOfInlinedMockDeclarationTest {
+
+    @InjectMocks private Receiver receiver;
+    @InjectMocks private Receiver spiedReceiver = spy(new Receiver());
+
+    private Antenna oldAntenna = mock(Antenna.class);
+    private Antenna satelliteAntenna = mock(Antenna.class);
+    private Antenna antenna = mock(Antenna.class, "dvbtAntenna");
+    private Tuner tuner = spy(new Tuner());
+
+    @Test
+    public void mock_declared_fields_shall_be_injected_too() throws Exception {
+        assertNotNull(receiver.oldAntenna);
+        assertNotNull(receiver.satelliteAntenna);
+        assertNotNull(receiver.dvbtAntenna);
+        assertNotNull(receiver.tuner);
+    }
+
+    @Test
+    public void unnamed_mocks_should_be_resolved_withe_their_field_names() throws Exception {
+        assertSame(oldAntenna, receiver.oldAntenna);
+        assertSame(satelliteAntenna, receiver.satelliteAntenna);
+    }
+
+    @Test
+    public void named_mocks_should_be_resolved_with_their_name() throws Exception {
+        assertSame(antenna, receiver.dvbtAntenna);
+    }
+
+
+    @Test
+    public void inject_mocks_even_in_declared_spy() throws Exception {
+        assertNotNull(spiedReceiver.oldAntenna);
+        assertNotNull(spiedReceiver.tuner);
+    }
+
+    // note that static class is not private !!
+    static class Receiver {
+        Antenna oldAntenna;
+        Antenna satelliteAntenna;
+        Antenna dvbtAntenna;
+        Tuner tuner;
+
+        public boolean tune() { return true; }
+    }
+
+    private static class Antenna { }
+    private static class Tuner { }
+
+}
diff --git a/src/test/java/org/mockitousage/annotation/MockInjectionUsingConstructorIssue421Test.java b/src/test/java/org/mockitousage/annotation/MockInjectionUsingConstructorIssue421Test.java
new file mode 100644
index 0000000..eb3e99f
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/MockInjectionUsingConstructorIssue421Test.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.examples.use.ArticleCalculator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MockInjectionUsingConstructorIssue421Test {
+
+    @Mock private ArticleCalculator calculator;
+
+    @InjectMocks private Issue421 issue421;
+
+    @Test
+    public void mockJustWorks() {
+        issue421.checkIfMockIsInjected();
+    }
+
+    static class Issue421 {
+
+        private ArticleCalculator calculator;
+
+        public Issue421(int a) {
+        }
+
+        public Issue421(ArticleCalculator calculator) {
+            this.calculator = calculator;
+        }
+
+        public void checkIfMockIsInjected(){
+            assertThat(MockUtil.isMock(calculator)).isTrue();
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/annotation/MockInjectionUsingConstructorTest.java b/src/test/java/org/mockitousage/annotation/MockInjectionUsingConstructorTest.java
new file mode 100644
index 0000000..38879dc
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/MockInjectionUsingConstructorTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.annotation;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.internal.TextListener;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitousage.examples.use.ArticleCalculator;
+import org.mockitousage.examples.use.ArticleDatabase;
+import org.mockitousage.examples.use.ArticleManager;
+
+import java.util.AbstractCollection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+public class MockInjectionUsingConstructorTest {
+
+    @Mock private ArticleCalculator calculator;
+    @Mock private ArticleDatabase database;
+
+    @InjectMocks private ArticleManager articleManager;
+    @Spy @InjectMocks private ArticleManager spiedArticleManager;
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    @Before public void before() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void shouldNotFailWhenNotInitialized() {
+        assertNotNull(articleManager);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void innerMockShouldRaiseAnExceptionThatChangesOuterMockBehavior() {
+        when(calculator.countArticles("new")).thenThrow(new IllegalArgumentException());
+
+        articleManager.updateArticleCounters("new");
+    }
+
+    @Test
+    public void mockJustWorks() {
+        articleManager.updateArticleCounters("new");
+    }
+
+    @Test
+    public void constructor_is_called_for_each_test_in_test_class() throws Exception {
+        // given
+        junit_test_with_3_tests_methods.constructor_instantiation = 0;
+        JUnitCore jUnitCore = new JUnitCore();
+        jUnitCore.addListener(new TextListener(System.out));
+
+        // when
+        jUnitCore.run(junit_test_with_3_tests_methods.class);
+
+        // then
+        assertThat(junit_test_with_3_tests_methods.constructor_instantiation).isEqualTo(3);
+    }
+
+    @Test
+    public void objects_created_with_constructor_initialization_can_be_spied() throws Exception {
+        assertFalse(MockUtil.isMock(articleManager));
+        assertTrue(MockUtil.isMock(spiedArticleManager));
+    }
+
+    @Test
+    public void should_report_failure_only_when_object_initialization_throws_exception() throws Exception {
+
+        try {
+            MockitoAnnotations.initMocks(new ATest());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage()).contains("failingConstructor").contains("constructor").contains("threw an exception");
+            assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
+        }
+    }
+
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class junit_test_with_3_tests_methods {
+        private static int constructor_instantiation = 0;
+
+        @Mock List<?> some_collaborator;
+        @InjectMocks some_class_with_parametered_constructor should_be_initialized_3_times;
+
+        @Test public void test_1() { }
+        @Test public void test_2() { }
+        @Test public void test_3() { }
+
+        private static class some_class_with_parametered_constructor {
+            public some_class_with_parametered_constructor(List<?> collaborator) {
+                constructor_instantiation++;
+            }
+        }
+    }
+
+    private static class FailingConstructor {
+        FailingConstructor(Set<?> set) {
+            throw new IllegalStateException("always fail");
+        }
+    }
+
+    @Ignore("don't run this code in the test runner")
+    private static class ATest {
+        @Mock Set<?> set;
+        @InjectMocks FailingConstructor failingConstructor;
+    }
+
+
+    @Test
+    public void injectMocksMustFailWithInterface() throws Exception {
+        class TestCase {
+            @InjectMocks
+            IMethods f;
+        }
+
+        exception.expect(MockitoException.class);
+        exception.expectMessage("Cannot instantiate @InjectMocks field named 'f'! Cause: the type 'IMethods' is an interface");
+
+
+        initMocks(new TestCase());
+    }
+
+    @Test
+    public void injectMocksMustFailWithEnum() throws Exception {
+        class TestCase {
+            @InjectMocks
+            TimeUnit f;
+        }
+
+        exception.expect(MockitoException.class);
+        exception.expectMessage("Cannot instantiate @InjectMocks field named 'f'! Cause: the type 'TimeUnit' is an enum");
+
+        initMocks(new TestCase());
+    }
+
+    @Test
+    public void injectMocksMustFailWithAbstractClass() throws Exception {
+        class TestCase {
+            @InjectMocks
+            AbstractCollection<?> f;
+        }
+
+        exception.expect(MockitoException.class);
+        exception.expectMessage("Cannot instantiate @InjectMocks field named 'f'! Cause: the type 'AbstractCollection' is an abstract class");
+
+        initMocks(new TestCase());
+    }
+
+    @Test
+    public void injectMocksMustFailWithNonStaticInnerClass() throws Exception {
+        class TestCase {
+            class InnerClass {}
+            @InjectMocks
+            InnerClass f;
+        }
+
+
+        exception.expect(MockitoException.class);
+        exception.expectMessage("Cannot instantiate @InjectMocks field named 'f'! Cause: the type 'InnerClass' is an inner non static class");
+
+        initMocks(new TestCase());
+    }
+
+    static class  StaticInnerClass {}
+    @Test
+    public void injectMocksMustSucceedWithStaticInnerClass() throws Exception {
+        class TestCase {
+            @InjectMocks
+            StaticInnerClass f;
+        }
+
+        TestCase testClass = new TestCase();
+        initMocks(testClass);
+
+        assertThat(testClass.f).isInstanceOf(StaticInnerClass.class);
+    }
+
+    @Test
+    public void injectMocksMustSucceedWithInstance() throws Exception {
+        class TestCase {
+            @InjectMocks
+            StaticInnerClass f = new StaticInnerClass();
+        }
+
+        TestCase testClass = new TestCase();
+        StaticInnerClass original = testClass.f;
+        initMocks(testClass);
+
+        assertThat(testClass.f).isSameAs(original);
+    }
+
+
+
+
+}
diff --git a/src/test/java/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java b/src/test/java/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java
new file mode 100644
index 0000000..1bf18a3
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.annotation;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.MockUtil;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static junit.framework.TestCase.*;
+
+@SuppressWarnings({"unchecked", "unused"})
+public class MockInjectionUsingSetterOrPropertyTest extends TestBase {
+
+    private SuperUnderTesting superUnderTestWithoutInjection = new SuperUnderTesting();
+    @InjectMocks private SuperUnderTesting superUnderTest = new SuperUnderTesting();
+    @InjectMocks private BaseUnderTesting baseUnderTest = new BaseUnderTesting();
+    @InjectMocks private SubUnderTesting subUnderTest = new SubUnderTesting();
+    @InjectMocks private OtherBaseUnderTesting otherBaseUnderTest = new OtherBaseUnderTesting();
+    @InjectMocks private HasTwoFieldsWithSameType hasTwoFieldsWithSameType = new HasTwoFieldsWithSameType();
+
+    private BaseUnderTesting baseUnderTestingInstance = new BaseUnderTesting();
+    @InjectMocks private BaseUnderTesting initializedBase = baseUnderTestingInstance;
+    @InjectMocks private BaseUnderTesting notInitializedBase;
+
+    @Spy @InjectMocks private SuperUnderTesting initializedSpy = new SuperUnderTesting();
+    @Spy @InjectMocks private SuperUnderTesting notInitializedSpy;
+
+    @Mock private Map<?, ?> map;
+    @Mock private List<?> list;
+    @Mock private Set<?> histogram1;
+    @Mock private Set<?> histogram2;
+    @Mock private IMethods candidate2;
+
+    @Spy private TreeSet<String> searchTree = new TreeSet<String>();
+
+    @Before
+    public void enforces_new_instances() {
+        // initMocks called in TestBase Before method, so instances are not the same
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void should_keep_same_instance_if_field_initialized() {
+        assertSame(baseUnderTestingInstance, initializedBase);
+    }
+
+    @Test
+    public void should_initialize_annotated_field_if_null() {
+        assertNotNull(notInitializedBase);
+    }
+
+    @Test
+    public void should_inject_mocks_in_spy() {
+        assertNotNull(initializedSpy.getAList());
+        assertTrue(MockUtil.isMock(initializedSpy));
+    }
+
+    @Test
+    public void should_initialize_spy_if_null_and_inject_mocks() {
+        assertNotNull(notInitializedSpy);
+        assertNotNull(notInitializedSpy.getAList());
+        assertTrue(MockUtil.isMock(notInitializedSpy));
+    }
+
+    @Test
+    public void should_inject_mocks_if_annotated() {
+        MockitoAnnotations.initMocks(this);
+        assertSame(list, superUnderTest.getAList());
+    }
+
+    @Test
+    public void should_not_inject_if_not_annotated() {
+        MockitoAnnotations.initMocks(this);
+        assertNull(superUnderTestWithoutInjection.getAList());
+    }
+
+    @Test
+    public void should_inject_mocks_for_class_hierarchy_if_annotated() {
+        MockitoAnnotations.initMocks(this);
+        assertSame(list, baseUnderTest.getAList());
+        assertSame(map, baseUnderTest.getAMap());
+    }
+
+    @Test
+    public void should_inject_mocks_by_name() {
+        MockitoAnnotations.initMocks(this);
+        assertSame(histogram1, subUnderTest.getHistogram1());
+        assertSame(histogram2, subUnderTest.getHistogram2());
+    }
+
+    @Test
+    public void should_inject_spies() {
+        MockitoAnnotations.initMocks(this);
+        assertSame(searchTree, otherBaseUnderTest.getSearchTree());
+    }
+
+    @Test
+    public void should_insert_into_field_with_matching_name_when_multiple_fields_of_same_type_exists_in_injectee() {
+        MockitoAnnotations.initMocks(this);
+        assertNull("not injected, no mock named 'candidate1'", hasTwoFieldsWithSameType.candidate1);
+        assertNotNull("injected, there's a mock named 'candidate2'", hasTwoFieldsWithSameType.candidate2);
+    }
+
+    @Test
+    public void should_instantiate_inject_mock_field_if_possible() throws Exception {
+        assertNotNull(notInitializedBase);
+    }
+
+    @Test
+    public void should_keep_instance_on_inject_mock_field_if_present() throws Exception {
+        assertSame(baseUnderTestingInstance, initializedBase);
+    }
+
+    @Test
+    public void should_report_nicely() throws Exception {
+        Object failing = new Object() {
+            @InjectMocks ThrowingConstructor failingConstructor;
+        };
+        try {
+            MockitoAnnotations.initMocks(failing);
+            fail();
+        } catch (MockitoException e) {
+            Assertions.assertThat(e.getMessage()).contains("failingConstructor").contains("constructor").contains("threw an exception");
+            Assertions.assertThat(e.getCause()).isInstanceOf(RuntimeException.class);
+        }
+    }
+
+    static class ThrowingConstructor {
+        ThrowingConstructor() { throw new RuntimeException("aha"); }
+    }
+
+    static class SuperUnderTesting {
+        private List<?> aList;
+
+        public List<?> getAList() { return aList; }
+    }
+
+    static class BaseUnderTesting extends SuperUnderTesting {
+        private Map<?, ?> aMap;
+
+        public Map<?, ?> getAMap() { return aMap; }
+    }
+
+    static class OtherBaseUnderTesting extends SuperUnderTesting {
+        private TreeSet<?> searchTree;
+
+        public TreeSet<?> getSearchTree() { return searchTree; }
+    }
+
+    static class SubUnderTesting extends BaseUnderTesting {
+        private Set<?> histogram1;
+        private Set<?> histogram2;
+
+        public Set<?> getHistogram1() { return histogram1; }
+        public Set<?> getHistogram2() { return histogram2; }
+    }
+
+    static class HasTwoFieldsWithSameType {
+        private IMethods candidate1;
+        private IMethods candidate2;
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/SpyAnnotationInitializedInBaseClassTest.java b/src/test/java/org/mockitousage/annotation/SpyAnnotationInitializedInBaseClassTest.java
new file mode 100644
index 0000000..4094d6a
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/SpyAnnotationInitializedInBaseClassTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.annotation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.internal.util.MockUtil;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.internal.util.MockUtil.isMock;
+
+@SuppressWarnings("unchecked")
+public class SpyAnnotationInitializedInBaseClassTest extends TestBase {
+
+    class BaseClass {
+
+        @Spy
+        List list = new LinkedList();
+    }
+
+    class SubClass extends BaseClass {
+
+    }
+
+    @Test
+    public void shouldInitSpiesInBaseClass() throws Exception {
+        //given
+        SubClass subClass = new SubClass();
+        //when
+        MockitoAnnotations.initMocks(subClass);
+        //then
+        assertTrue(MockUtil.isMock(subClass.list));
+    }
+
+    @Before
+    @Override
+    public void init() {
+        //we need to get rid of parent implementation this time
+    }
+
+    @Before
+    public void before() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Spy
+    List spyInBaseclass = new LinkedList();
+
+    public static class SubTest extends SpyAnnotationInitializedInBaseClassTest {
+
+        @Spy
+        List spyInSubclass = new LinkedList();
+
+        @Test
+        public void shouldInitSpiesInHierarchy() throws Exception {
+            assertTrue(isMock(spyInSubclass));
+            assertTrue(isMock(spyInBaseclass));
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/SpyAnnotationTest.java b/src/test/java/org/mockitousage/annotation/SpyAnnotationTest.java
new file mode 100644
index 0000000..2423822
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/SpyAnnotationTest.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.annotation;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("unused")
+public class SpyAnnotationTest extends TestBase {
+
+    @Spy
+    final List<String> spiedList = new ArrayList<String>();
+
+    @Spy
+    InnerStaticClassWithNoArgConstructor staticTypeWithNoArgConstructor;
+
+    @Spy
+    InnerStaticClassWithoutDefinedConstructor staticTypeWithoutDefinedConstructor;
+
+    @Rule
+    public final ExpectedException shouldThrow = ExpectedException.none();
+
+    @Test
+    public void should_init_spy_by_instance() throws Exception {
+        doReturn("foo").when(spiedList).get(10);
+        assertEquals("foo", spiedList.get(10));
+        assertTrue(spiedList.isEmpty());
+    }
+
+    @Test
+    public void should_init_spy_and_automatically_create_instance() throws Exception {
+        when(staticTypeWithNoArgConstructor.toString()).thenReturn("x");
+        when(staticTypeWithoutDefinedConstructor.toString()).thenReturn("y");
+        assertEquals("x", staticTypeWithNoArgConstructor.toString());
+        assertEquals("y", staticTypeWithoutDefinedConstructor.toString());
+    }
+
+    @Test
+    public void should_allow_spying_on_interfaces() throws Exception {
+        class WithSpy {
+            @Spy
+            List<String> list;
+        }
+
+        WithSpy withSpy = new WithSpy();
+        MockitoAnnotations.initMocks(withSpy);
+        when(withSpy.list.size()).thenReturn(3);
+        assertEquals(3, withSpy.list.size());
+    }
+
+    @Test
+    public void should_allow_spying_on_interfaces_when_instance_is_concrete() throws Exception {
+        class WithSpy {
+            @Spy
+            List<String> list = new LinkedList<String>();
+        }
+        WithSpy withSpy = new WithSpy();
+
+        //when
+        MockitoAnnotations.initMocks(withSpy);
+
+        //then
+        verify(withSpy.list, never()).clear();
+    }
+
+    @Test
+    public void should_report_when_no_arg_less_constructor() throws Exception {
+        class FailingSpy {
+            @Spy
+            NoValidConstructor noValidConstructor;
+        }
+
+        try {
+            MockitoAnnotations.initMocks(new FailingSpy());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage()).contains("Please ensure that the type")
+                    .contains(NoValidConstructor.class.getSimpleName())
+                    .contains("has a no-arg constructor");
+        }
+    }
+
+    @Test
+    public void should_report_when_constructor_is_explosive() throws Exception {
+        class FailingSpy {
+            @Spy
+            ThrowingConstructor throwingConstructor;
+        }
+
+        try {
+            MockitoAnnotations.initMocks(new FailingSpy());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage()).contains("Unable to create mock instance");
+        }
+    }
+
+    @Test
+    public void should_spy_abstract_class() throws Exception {
+        class SpyAbstractClass {
+            @Spy
+            AbstractList<String> list;
+
+            List<String> asSingletonList(String s) {
+                when(list.size()).thenReturn(1);
+                when(list.get(0)).thenReturn(s);
+                return list;
+            }
+        }
+        SpyAbstractClass withSpy = new SpyAbstractClass();
+        MockitoAnnotations.initMocks(withSpy);
+        assertEquals(Arrays.asList("a"), withSpy.asSingletonList("a"));
+    }
+
+    @Test
+    public void should_spy_inner_class() throws Exception {
+
+        class WithMockAndSpy {
+            @Spy
+            private InnerStrength strength;
+            @Mock
+            private List<String> list;
+
+            abstract class InnerStrength {
+                private final String name;
+
+                InnerStrength() {
+                    // Make sure that @Mock fields are always injected before @Spy fields.
+                    assertNotNull(list);
+                    // Make sure constructor is indeed called.
+                    this.name = "inner";
+                }
+
+                abstract String strength();
+
+                String fullStrength() {
+                    return name + " " + strength();
+                }
+            }
+        }
+        WithMockAndSpy outer = new WithMockAndSpy();
+        MockitoAnnotations.initMocks(outer);
+        when(outer.strength.strength()).thenReturn("strength");
+        assertEquals("inner strength", outer.strength.fullStrength());
+    }
+
+    @Test(expected = IndexOutOfBoundsException.class)
+    public void should_reset_spy() throws Exception {
+        spiedList.get(10); // see shouldInitSpy
+    }
+
+    @Test
+    public void should_report_when_enclosing_instance_is_needed() throws Exception {
+        class Outer {
+            class Inner {
+            }
+        }
+        class WithSpy {
+            @Spy
+            private Outer.Inner inner;
+        }
+        try {
+            MockitoAnnotations.initMocks(new WithSpy());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("@Spy annotation can only initialize inner classes");
+        }
+    }
+
+    @Test
+    public void should_report_private_inner_not_supported() throws Exception {
+        try {
+            MockitoAnnotations.initMocks(new WithInnerPrivate());
+            fail();
+        } catch (MockitoException e) {
+            // Currently fails at instantiation time, because the mock subclass don't have the
+            // 1-arg constructor expected for the outerclass.
+            // org.mockito.internal.creation.instance.ConstructorInstantiator.withParams()
+            assertThat(e).hasMessageContaining("Unable to initialize @Spy annotated field 'spy_field'")
+                    .hasMessageContaining(WithInnerPrivate.InnerPrivate.class.getSimpleName());
+        }
+    }
+
+    @Test
+    public void should_report_private_abstract_inner_not_supported() throws Exception {
+        try {
+            MockitoAnnotations.initMocks(new WithInnerPrivateAbstract());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("@Spy annotation can't initialize private abstract inner classes")
+                    .hasMessageContaining(WithInnerPrivateAbstract.class.getSimpleName())
+                    .hasMessageContaining(WithInnerPrivateAbstract.InnerPrivateAbstract.class.getSimpleName())
+                    .hasMessageContaining("You should augment the visibility of this inner class");
+        }
+    }
+
+    @Test
+    public void should_report_private_static_abstract_inner_not_supported() throws Exception {
+        try {
+            MockitoAnnotations.initMocks(new WithInnerPrivateStaticAbstract());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("@Spy annotation can't initialize private abstract inner classes")
+                    .hasMessageContaining(WithInnerPrivateStaticAbstract.class.getSimpleName())
+                    .hasMessageContaining(WithInnerPrivateStaticAbstract.InnerPrivateStaticAbstract.class.getSimpleName())
+                    .hasMessageContaining("You should augment the visibility of this inner class");
+        }
+    }
+
+    static class WithInnerPrivateStaticAbstract {
+        @Spy
+        private InnerPrivateStaticAbstract spy_field;
+
+        private static abstract class InnerPrivateStaticAbstract {
+        }
+    }
+    static class WithInnerPrivateAbstract {
+        @Spy
+        private InnerPrivateAbstract spy_field;
+
+        public void some_method() {
+            new InnerPrivateConcrete();
+        }
+
+        private abstract class InnerPrivateAbstract {
+        }
+
+        private class InnerPrivateConcrete extends InnerPrivateAbstract {
+
+        }
+    }
+
+    static class WithInnerPrivate {
+        @Spy
+        private InnerPrivate spy_field;
+
+        private class InnerPrivate {
+        }
+
+        private class InnerPrivateSub extends InnerPrivate {}
+    }
+
+    static class InnerStaticClassWithoutDefinedConstructor {
+    }
+
+    static class InnerStaticClassWithNoArgConstructor {
+        InnerStaticClassWithNoArgConstructor() {
+        }
+
+        InnerStaticClassWithNoArgConstructor(String f) {
+        }
+    }
+
+    static class NoValidConstructor {
+        NoValidConstructor(String f) {
+        }
+    }
+
+    static class ThrowingConstructor {
+        ThrowingConstructor() {
+            throw new RuntimeException("boo!");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/SpyInjectionTest.java b/src/test/java/org/mockitousage/annotation/SpyInjectionTest.java
new file mode 100644
index 0000000..32b37fd
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/SpyInjectionTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.annotation;
+
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+import org.mockito.internal.util.MockUtil;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class SpyInjectionTest extends TestBase {
+
+    @Spy List<Object> spy = new LinkedList<Object>();
+    @InjectMocks HasSpy hasSpy = new HasSpy();
+
+    static class HasSpy {
+        private List<?> spy;
+        public void setSpy(List<?> spy) {
+            this.spy = spy;
+        }
+    }
+
+    @Test
+    public void shouldDoStuff() throws Exception {
+        MockUtil.isMock(hasSpy.spy);
+    }
+}
diff --git a/src/test/java/org/mockitousage/annotation/WrongSetOfAnnotationsTest.java b/src/test/java/org/mockitousage/annotation/WrongSetOfAnnotationsTest.java
new file mode 100644
index 0000000..ef0a646
--- /dev/null
+++ b/src/test/java/org/mockitousage/annotation/WrongSetOfAnnotationsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.annotation;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.*;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+
+public class WrongSetOfAnnotationsTest extends TestBase {
+
+    @Test(expected=MockitoException.class)
+    public void should_not_allow_Mock_and_Spy() throws Exception {
+        MockitoAnnotations.initMocks(new Object() {
+            @Mock @Spy List<?> mock;
+        });
+    }
+
+    @Test
+    public void should_not_allow_Spy_and_InjectMocks_on_interfaces() throws Exception {
+        try {
+            MockitoAnnotations.initMocks(new Object() { @InjectMocks @Spy List<?> mock; });
+            fail();
+        } catch (MockitoException me) {
+            Assertions.assertThat(me.getMessage()).contains("'List' is an interface");
+        }
+    }
+
+    @Test
+    public void should_allow_Spy_and_InjectMocks() throws Exception {
+        MockitoAnnotations.initMocks(new Object() {
+            @InjectMocks
+            @Spy
+            WithDependency mock;
+        });
+    }
+    static class WithDependency { List<?> list; }
+
+    @Test(expected=MockitoException.class)
+    public void should_not_allow_Mock_and_InjectMocks() throws Exception {
+        MockitoAnnotations.initMocks(new Object() {
+            @InjectMocks @Mock List<?> mock;
+        });
+    }
+
+    @Test(expected=MockitoException.class)
+    public void should_not_allow_Captor_and_Mock() throws Exception {
+        MockitoAnnotations.initMocks(new Object() {
+            @Mock @Captor ArgumentCaptor<?> captor;
+        });
+    }
+
+    @Test(expected=MockitoException.class)
+    public void should_not_allow_Captor_and_Spy() throws Exception {
+        MockitoAnnotations.initMocks(new Object() {
+            @Spy @Captor ArgumentCaptor<?> captor;
+        });
+    }
+
+    @Test(expected=MockitoException.class)
+    public void should_not_allow_Captor_and_InjectMocks() throws Exception {
+        MockitoAnnotations.initMocks(new Object() {
+            @InjectMocks @Captor ArgumentCaptor<?> captor;
+        });
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/MockAccessTest.java b/src/test/java/org/mockitousage/basicapi/MockAccessTest.java
new file mode 100644
index 0000000..84d45e7
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/MockAccessTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.basicapi;
+
+
+import org.junit.Test;
+
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MockAccessTest {
+
+    @Test
+    public void shouldAllowStubbedMockReferenceAccess() throws Exception {
+        Set<?> expectedMock = mock(Set.class);
+
+        Set<?> returnedMock = when(expectedMock.isEmpty()).thenReturn(false).getMock();
+
+        assertEquals(expectedMock, returnedMock);
+    }
+
+    @Test
+    public void stubbedMockShouldWorkAsUsual() throws Exception {
+        Set<?> returnedMock = when(mock(Set.class).isEmpty()).thenReturn(false, true).getMock();
+
+        assertEquals(false, returnedMock.isEmpty());
+        assertEquals(true, returnedMock.isEmpty());
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/MockingMultipleInterfacesTest.java b/src/test/java/org/mockitousage/basicapi/MockingMultipleInterfacesTest.java
new file mode 100644
index 0000000..ae5edd5
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/MockingMultipleInterfacesTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+import static org.mockitoutil.ClassLoaders.inMemoryClassLoader;
+import static org.mockitoutil.SimpleClassGenerator.makeMarkerInterface;
+
+// See issue 453
+public class MockingMultipleInterfacesTest {
+
+    class Foo {}
+    interface IFoo {}
+    interface IBar {}
+
+    @Test
+    public void should_allow_multiple_interfaces() {
+        //when
+        Foo mock = mock(Foo.class, withSettings().extraInterfaces(IFoo.class, IBar.class));
+
+        //then
+        assertThat(mock).isInstanceOf(IFoo.class);
+        assertThat(mock).isInstanceOf(IBar.class);
+    }
+
+    @Test
+    public void should_scream_when_null_passed_instead_of_an_interface() {
+        try {
+            //when
+            mock(Foo.class, withSettings().extraInterfaces(IFoo.class, null));
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e.getMessage()).contains("extraInterfaces() does not accept null parameters");
+        }
+    }
+
+    @Test
+    public void should_scream_when_no_args_passed() {
+        try {
+            //when
+            mock(Foo.class, withSettings().extraInterfaces());
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e.getMessage()).contains("extraInterfaces() requires at least one interface");
+        }
+    }
+
+    @Test
+    public void should_scream_when_null_passed_instead_of_an_array() {
+        try {
+            //when
+            mock(Foo.class, withSettings().extraInterfaces((Class[]) null));
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e.getMessage()).contains("extraInterfaces() requires at least one interface");
+        }
+    }
+
+    @Test
+    public void should_scream_when_non_interface_passed() {
+        try {
+            //when
+            mock(Foo.class, withSettings().extraInterfaces(Foo.class));
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e.getMessage()).contains("Foo which is not an interface");
+        }
+    }
+
+    @Test
+    public void should_scream_when_the_same_interfaces_passed() {
+        try {
+            //when
+            mock(IMethods.class, withSettings().extraInterfaces(IMethods.class));
+            fail();
+        } catch (MockitoException e) {
+            //then
+            assertThat(e.getMessage()).contains("You mocked following type: IMethods");
+        }
+    }
+
+
+    @Test
+    public void should_mock_class_with_interfaces_of_different_class_loader_AND_different_classpaths() throws ClassNotFoundException {
+        // Note : if classes are in the same classpath, SearchingClassLoader can find the class/classes and load them in the first matching classloader
+        Class<?> interface1 = inMemoryClassLoader()
+                .withClassDefinition("test.Interface1", makeMarkerInterface("test.Interface1"))
+                .build()
+                .loadClass("test.Interface1");
+        Class<?> interface2 = inMemoryClassLoader()
+                .withClassDefinition("test.Interface2", makeMarkerInterface("test.Interface2"))
+                .build()
+                .loadClass("test.Interface2");
+
+        Object mocked = mock(interface1, withSettings().extraInterfaces(interface2));
+        assertThat(interface2.isInstance(mocked)).describedAs("mock should be assignable from interface2 type").isTrue();
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java b/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java
new file mode 100644
index 0000000..74935bd
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.SmartNullPointerException;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class MocksCreationTest extends TestBase {
+
+    private class HasPrivateConstructor {}
+
+    @Test
+    public void shouldCreateMockWhenConstructorIsPrivate() {
+        assertNotNull(Mockito.mock(HasPrivateConstructor.class));
+    }
+
+    @Test
+    public void shouldCombineMockNameAndSmartNulls() {
+        //given
+        IMethods mock = mock(IMethods.class, withSettings()
+            .defaultAnswer(RETURNS_SMART_NULLS)
+            .name("great mockie"));
+
+        //when
+        IMethods smartNull = mock.iMethodsReturningMethod();
+        String name = mock.toString();
+
+        //then
+        assertThat(name).contains("great mockie");
+        //and
+        try {
+            smartNull.simpleMethod();
+            fail();
+        } catch(SmartNullPointerException e) {}
+    }
+
+    @Test
+    public void shouldCombineMockNameAndExtraInterfaces() {
+        //given
+        IMethods mock = mock(IMethods.class, withSettings()
+                .extraInterfaces(List.class)
+                .name("great mockie"));
+
+        //when
+        String name = mock.toString();
+
+        //then
+        assertThat(name).contains("great mockie");
+        //and
+        assertTrue(mock instanceof List);
+    }
+
+    @Test
+    public void shouldSpecifyMockNameViaSettings() {
+        //given
+        IMethods mock = mock(IMethods.class, withSettings().name("great mockie"));
+
+        //when
+        String name = mock.toString();
+
+        //then
+        assertThat(name).contains("great mockie");
+    }
+
+    @Test
+    public void shouldScreamWhenSpyCreatedWithWrongType() {
+        //given
+        List list = new LinkedList();
+        try {
+            //when
+            mock(List.class, withSettings().spiedInstance(list));
+            fail();
+            //then
+        } catch (MockitoException e) {}
+    }
+
+    @Test
+    public void shouldAllowCreatingSpiesWithCorrectType() {
+        List list = new LinkedList();
+        mock(LinkedList.class, withSettings().spiedInstance(list));
+    }
+
+    @Test
+    public void shouldAllowInlineMockCreation() throws Exception {
+        when(mock(Set.class).isEmpty()).thenReturn(false);
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/basicapi/MocksSerializationForAnnotationTest.java b/src/test/java/org/mockitousage/basicapi/MocksSerializationForAnnotationTest.java
new file mode 100644
index 0000000..405f35d
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/MocksSerializationForAnnotationTest.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.matchers.Any;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Observable;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.*;
+import static org.mockitoutil.SimpleSerializationUtil.*;
+
+@SuppressWarnings({"unchecked", "serial"})
+public class MocksSerializationForAnnotationTest extends TestBase implements Serializable {
+
+    private static final long serialVersionUID = 6160482220413048624L;
+
+    @Mock Any any;
+    @Mock(serializable=true) Bar barMock;
+    @Mock(serializable=true) IMethods imethodsMock;
+    @Mock(serializable=true) IMethods imethodsMock2;
+    @Mock(serializable=true) Any anyMock;
+    @Mock(serializable=true) AlreadySerializable alreadySerializableMock;
+    @Mock(extraInterfaces={List.class},serializable=true) IMethods imethodsWithExtraInterfacesMock;
+
+    @Test
+    public void should_allow_throws_exception_to_be_serializable() throws Exception {
+        // given
+        when(barMock.doSomething()).thenAnswer(new ThrowsException(new RuntimeException()));
+
+        //when-serialize then-deserialize
+        serializeAndBack(barMock);
+    }
+
+    @Test
+    public void should_allow_mock_to_be_serializable() throws Exception {
+        // when-serialize then-deserialize
+        serializeAndBack(imethodsMock);
+    }
+
+    @Test
+    public void should_allow_mock_and_boolean_value_to_serializable() throws Exception {
+        // given
+        when(imethodsMock.booleanReturningMethod()).thenReturn(true);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertTrue(readObject.booleanReturningMethod());
+    }
+
+    @Test
+    public void should_allow_mock_and_string_value_to_be_serializable() throws Exception {
+        // given
+        String value = "value";
+        when(imethodsMock.stringReturningMethod()).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.stringReturningMethod());
+    }
+
+    @Test
+    public void should_all_mock_and_serializable_value_to_be_serialized() throws Exception {
+        // given
+        List<?> value = Collections.emptyList();
+        when(imethodsMock.objectReturningMethodNoArgs()).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.objectReturningMethodNoArgs());
+    }
+
+    @Test
+    public void should_serialize_method_call_with_parameters_that_are_serializable() throws Exception {
+        List<?> value = Collections.emptyList();
+        when(imethodsMock.objectArgMethod(value)).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.objectArgMethod(value));
+    }
+
+    @Test
+    public void should_serialize_method_calls_using_any_string_matcher() throws Exception {
+        List<?> value = Collections.emptyList();
+        when(imethodsMock.objectArgMethod(anyString())).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.objectArgMethod(""));
+    }
+
+    @Test
+    public void should_verify_called_n_times_for_serialized_mock() throws Exception {
+        List<?> value = Collections.emptyList();
+        when(imethodsMock.objectArgMethod(anyString())).thenReturn(value);
+        imethodsMock.objectArgMethod("");
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        verify(readObject, times(1)).objectArgMethod("");
+    }
+
+    @Test
+    public void should_verify_even_if_some_methods_called_after_serialization() throws Exception {
+
+        // when
+        imethodsMock.simpleMethod(1);
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        readObject.simpleMethod(1);
+
+        // then
+        verify(readObject, times(2)).simpleMethod(1);
+
+        //this test is working because it seems that java serialization mechanism replaces all instances
+        //of serialized object in the object graph (if there are any)
+    }
+
+    class Bar implements Serializable {
+        Foo foo;
+
+        public Foo doSomething() {
+            return foo;
+        }
+    }
+
+    class Foo implements Serializable {
+        Bar bar;
+        Foo() {
+            bar = new Bar();
+            bar.foo = this;
+        }
+    }
+
+    @Test
+    public void should_serialization_work() throws Exception {
+        //given
+        Foo foo = new Foo();
+        //when
+        foo = serializeAndBack(foo);
+        //then
+        assertSame(foo, foo.bar.foo);
+    }
+
+    @Test
+    public void should_stub_even_if_some_methods_called_after_serialization() throws Exception {
+        //given
+        // when
+        when(imethodsMock.simpleMethod(1)).thenReturn("foo");
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        when(readObject.simpleMethod(2)).thenReturn("bar");
+
+        // then
+        assertEquals("foo", readObject.simpleMethod(1));
+        assertEquals("bar", readObject.simpleMethod(2));
+    }
+
+    @Test
+    public void should_verify_call_order_for_serialized_mock() throws Exception {
+        imethodsMock.arrayReturningMethod();
+        imethodsMock2.arrayReturningMethod();
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+        ByteArrayOutputStream serialized2 = serializeMock(imethodsMock2);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        IMethods readObject2 = deserializeMock(serialized2, IMethods.class);
+        InOrder inOrder = inOrder(readObject, readObject2);
+        inOrder.verify(readObject).arrayReturningMethod();
+        inOrder.verify(readObject2).arrayReturningMethod();
+    }
+
+    @Test
+    public void should_remember_interactions_for_serialized_mock() throws Exception {
+        List<?> value = Collections.emptyList();
+        when(imethodsMock.objectArgMethod(anyString())).thenReturn(value);
+        imethodsMock.objectArgMethod("happened");
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        verify(readObject, never()).objectArgMethod("never happened");
+    }
+
+    @Test
+    public void should_serialize_with_stubbing_callback() throws Exception {
+
+        // given
+        CustomAnswersMustImplementSerializableForSerializationToWork answer =
+            new CustomAnswersMustImplementSerializableForSerializationToWork();
+        answer.string = "return value";
+        when(imethodsMock.objectArgMethod(anyString())).thenAnswer(answer);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(imethodsMock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(answer.string, readObject.objectArgMethod(""));
+    }
+
+    static class CustomAnswersMustImplementSerializableForSerializationToWork
+        implements Answer<Object>, Serializable {
+        private String string;
+        public Object answer(InvocationOnMock invocation) throws Throwable {
+            invocation.getArguments();
+            invocation.getMock();
+            return string;
+        }
+    }
+
+    @Test
+    public void should_serialize_with_real_object_spy() throws Exception {
+        // given
+        List<Object> list = new ArrayList<Object>();
+        List<Object> spy = mock(ArrayList.class, withSettings()
+                        .spiedInstance(list)
+                        .defaultAnswer(CALLS_REAL_METHODS)
+                        .serializable());
+        when(spy.size()).thenReturn(100);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(spy);
+
+        // then
+        List<?> readObject = deserializeMock(serialized, List.class);
+        assertEquals(100, readObject.size());
+    }
+
+    @Test
+    public void should_serialize_object_mock() throws Exception {
+        // when
+        ByteArrayOutputStream serialized = serializeMock(any);
+
+        // then
+        deserializeMock(serialized, Any.class);
+    }
+
+    @Test
+    public void should_serialize_real_partial_mock() throws Exception {
+        // given
+        when(anyMock.matches(anyObject())).thenCallRealMethod();
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(anyMock);
+
+        // then
+        Any readObject = deserializeMock(serialized, Any.class);
+        readObject.matches("");
+    }
+
+    class AlreadySerializable implements Serializable {}
+
+    @Test
+    public void should_serialize_already_serializable_class() throws Exception {
+        // given
+        when(alreadySerializableMock.toString()).thenReturn("foo");
+
+        // when
+        alreadySerializableMock = serializeAndBack(alreadySerializableMock);
+
+        // then
+        assertEquals("foo", alreadySerializableMock.toString());
+    }
+
+    @Test
+    public void should_be_serialize_and_have_extra_interfaces() throws Exception {
+        //then
+        Assertions.assertThat((Object) serializeAndBack((List) imethodsWithExtraInterfacesMock))
+                .isInstanceOf(List.class)
+                .isInstanceOf(IMethods.class);
+    }
+
+
+
+    static class NotSerializableAndNoDefaultConstructor {
+        NotSerializableAndNoDefaultConstructor(Observable o) { super(); }
+    }
+
+
+
+    static class SerializableAndNoDefaultConstructor implements Serializable {
+        SerializableAndNoDefaultConstructor(Observable o) { super(); }
+    }
+
+    public static class TestClassThatHoldValidField {
+        @Mock(serializable=true)
+        SerializableAndNoDefaultConstructor serializableAndNoDefaultConstructor;
+    }
+
+    @Test
+    public void should_be_able_to_serialize_type_that_implements_Serializable_but_but_dont_declare_a_no_arg_constructor() throws Exception {
+        TestClassThatHoldValidField testClass = new TestClassThatHoldValidField();
+        MockitoAnnotations.initMocks(testClass);
+
+        serializeAndBack(testClass.serializableAndNoDefaultConstructor);
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/MocksSerializationTest.java b/src/test/java/org/mockitousage/basicapi/MocksSerializationTest.java
new file mode 100644
index 0000000..1e82a06
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/MocksSerializationTest.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.mockito.internal.matchers.Any;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitousage.IMethods;
+import org.mockitoutil.SimpleSerializationUtil;
+import org.mockitoutil.TestBase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Observable;
+
+import static junit.framework.TestCase.*;
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.Mockito.*;
+import static org.mockitoutil.SimpleSerializationUtil.*;
+
+@SuppressWarnings({"unchecked", "serial"})
+public class MocksSerializationTest extends TestBase implements Serializable {
+
+    private static final long serialVersionUID = 6160482220413048624L;
+
+    @Test
+    public void should_allow_throws_exception_to_be_serializable() throws Exception {
+        // given
+        Bar mock = mock(Bar.class, new ThrowsException(new RuntimeException()));
+        // when-serialize then-deserialize
+        serializeAndBack(mock);
+    }
+
+    @Test
+    public void should_allow_method_delegation() throws Exception {
+        // given
+        Bar barMock = mock(Bar.class, withSettings().serializable());
+        Foo fooMock = mock(Foo.class);
+        when(barMock.doSomething()).thenAnswer(new ThrowsException(new RuntimeException()));
+
+        //when-serialize then-deserialize
+        serializeAndBack(barMock);
+    }
+
+    @Test
+    public void should_allow_mock_to_be_serializable() throws Exception {
+        // given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+
+        // when-serialize then-deserialize
+        serializeAndBack(mock);
+    }
+
+    @Test
+    public void should_allow_mock_and_boolean_value_to_serializable() throws Exception {
+        // given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        when(mock.booleanReturningMethod()).thenReturn(true);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertTrue(readObject.booleanReturningMethod());
+    }
+
+    @Test
+    public void should_allow_mock_and_string_value_to_be_serializable() throws Exception {
+        // given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        String value = "value";
+        when(mock.stringReturningMethod()).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.stringReturningMethod());
+    }
+
+    @Test
+    public void should_all_mock_and_serializable_value_to_be_serialized() throws Exception {
+        // given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        List<?> value = Collections.emptyList();
+        when(mock.objectReturningMethodNoArgs()).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.objectReturningMethodNoArgs());
+    }
+
+    @Test
+    public void should_serialize_method_call_with_parameters_that_are_serializable() throws Exception {
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        List<?> value = Collections.emptyList();
+        when(mock.objectArgMethod(value)).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.objectArgMethod(value));
+    }
+
+    @Test
+    public void should_serialize_method_calls_using_any_string_matcher() throws Exception {
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        List<?> value = Collections.emptyList();
+        when(mock.objectArgMethod(anyString())).thenReturn(value);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(value, readObject.objectArgMethod(""));
+    }
+
+    @Test
+    public void should_verify_called_n_times_for_serialized_mock() throws Exception {
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        List<?> value = Collections.emptyList();
+        when(mock.objectArgMethod(anyString())).thenReturn(value);
+        mock.objectArgMethod("");
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        verify(readObject, times(1)).objectArgMethod("");
+    }
+
+    @Test
+    public void should_verify_even_if_some_methods_called_after_serialization() throws Exception {
+        //given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+
+        // when
+        mock.simpleMethod(1);
+        ByteArrayOutputStream serialized = serializeMock(mock);
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        readObject.simpleMethod(1);
+
+        // then
+        verify(readObject, times(2)).simpleMethod(1);
+
+        //this test is working because it seems that java serialization mechanism replaces all instances
+        //of serialized object in the object graph (if there are any)
+    }
+
+    class Bar implements Serializable {
+        Foo foo;
+
+        public Foo doSomething() {
+            return foo;
+        }
+    }
+
+    class Foo implements Serializable {
+        Bar bar;
+        Foo() {
+            bar = new Bar();
+            bar.foo = this;
+        }
+    }
+
+    @Test
+    public void should_serialization_work() throws Exception {
+        //given
+        Foo foo = new Foo();
+        //when
+        foo = serializeAndBack(foo);
+        //then
+        assertSame(foo, foo.bar.foo);
+    }
+
+    @Test
+    public void should_stub_even_if_some_methods_called_after_serialization() throws Exception {
+        //given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+
+        // when
+        when(mock.simpleMethod(1)).thenReturn("foo");
+        ByteArrayOutputStream serialized = serializeMock(mock);
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        when(readObject.simpleMethod(2)).thenReturn("bar");
+
+        // then
+        assertEquals("foo", readObject.simpleMethod(1));
+        assertEquals("bar", readObject.simpleMethod(2));
+    }
+
+    @Test
+    public void should_verify_call_order_for_serialized_mock() throws Exception {
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        IMethods mock2 = mock(IMethods.class, withSettings().serializable());
+        mock.arrayReturningMethod();
+        mock2.arrayReturningMethod();
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+        ByteArrayOutputStream serialized2 = serializeMock(mock2);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        IMethods readObject2 = deserializeMock(serialized2, IMethods.class);
+        InOrder inOrder = inOrder(readObject, readObject2);
+        inOrder.verify(readObject).arrayReturningMethod();
+        inOrder.verify(readObject2).arrayReturningMethod();
+    }
+
+    @Test
+    public void should_remember_interactions_for_serialized_mock() throws Exception {
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        List<?> value = Collections.emptyList();
+        when(mock.objectArgMethod(anyString())).thenReturn(value);
+        mock.objectArgMethod("happened");
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        verify(readObject, never()).objectArgMethod("never happened");
+    }
+
+    @Test
+    public void should_serialize_with_stubbing_callback() throws Exception {
+
+        // given
+        IMethods mock = mock(IMethods.class, withSettings().serializable());
+        CustomAnswersMustImplementSerializableForSerializationToWork answer =
+                new CustomAnswersMustImplementSerializableForSerializationToWork();
+        answer.string = "return value";
+        when(mock.objectArgMethod(anyString())).thenAnswer(answer);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        IMethods readObject = deserializeMock(serialized, IMethods.class);
+        assertEquals(answer.string, readObject.objectArgMethod(""));
+    }
+
+    class CustomAnswersMustImplementSerializableForSerializationToWork
+            implements Answer<Object>, Serializable {
+        private String string;
+        public Object answer(InvocationOnMock invocation) throws Throwable {
+            invocation.getArguments();
+            invocation.getMock();
+            return string;
+        }
+    }
+
+    @Test
+    public void should_serialize_with_real_object_spy() throws Exception {
+        // given
+        List<Object> list = new ArrayList<Object>();
+        List<Object> spy = mock(ArrayList.class, withSettings()
+                .spiedInstance(list)
+                .defaultAnswer(CALLS_REAL_METHODS)
+                .serializable());
+        when(spy.size()).thenReturn(100);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(spy);
+
+        // then
+        List<?> readObject = deserializeMock(serialized, List.class);
+        assertEquals(100, readObject.size());
+    }
+
+    @Test
+    public void should_serialize_object_mock() throws Exception {
+        // given
+        Any mock = mock(Any.class);
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        deserializeMock(serialized, Any.class);
+    }
+
+    @Test
+    public void should_serialize_real_partial_mock() throws Exception {
+        // given
+        Any mock = mock(Any.class, withSettings().serializable());
+        when(mock.matches(anyObject())).thenCallRealMethod();
+
+        // when
+        ByteArrayOutputStream serialized = serializeMock(mock);
+
+        // then
+        Any readObject = deserializeMock(serialized, Any.class);
+        readObject.matches("");
+    }
+
+    class AlreadySerializable implements Serializable {}
+
+    @Test
+    public void should_serialize_already_serializable_class() throws Exception {
+        // given
+        AlreadySerializable mock = mock(AlreadySerializable.class, withSettings().serializable());
+        when(mock.toString()).thenReturn("foo");
+
+        // when
+        mock = serializeAndBack(mock);
+
+        // then
+        assertEquals("foo", mock.toString());
+    }
+
+    @Test
+    public void should_be_serialize_and_have_extra_interfaces() throws Exception {
+        //when
+        IMethods mock = mock(IMethods.class, withSettings().serializable().extraInterfaces(List.class));
+        IMethods mockTwo = mock(IMethods.class, withSettings().extraInterfaces(List.class).serializable());
+
+        //then
+        Assertions.assertThat((Object) serializeAndBack((List) mock))
+                .isInstanceOf(List.class)
+                .isInstanceOf(IMethods.class);
+        Assertions.assertThat((Object) serializeAndBack((List) mockTwo))
+                .isInstanceOf(List.class)
+                .isInstanceOf(IMethods.class);
+    }
+
+
+
+    static class SerializableAndNoDefaultConstructor implements Serializable {
+        SerializableAndNoDefaultConstructor(Observable o) { super(); }
+    }
+
+    @Test
+    public void should_be_able_to_serialize_type_that_implements_Serializable_but_but_dont_declare_a_no_arg_constructor() throws Exception {
+        serializeAndBack(mock(SerializableAndNoDefaultConstructor.class));
+    }
+
+
+
+    public static class AClassWithPrivateNoArgConstructor {
+        private AClassWithPrivateNoArgConstructor() {}
+        List returningSomething() { return Collections.emptyList(); }
+    }
+
+    @Test
+    public void private_constructor_currently_not_supported_at_the_moment_at_deserialization_time() throws Exception {
+        // given
+        AClassWithPrivateNoArgConstructor mockWithPrivateConstructor = Mockito.mock(
+                AClassWithPrivateNoArgConstructor.class,
+                Mockito.withSettings().serializable()
+        );
+
+        try {
+            // when
+            SimpleSerializationUtil.serializeAndBack(mockWithPrivateConstructor);
+            fail("should have thrown an ObjectStreamException or a subclass of it");
+        } catch (ObjectStreamException e) {
+            // then
+            Assertions.assertThat(e.toString()).contains("no valid constructor");
+        }
+    }
+
+
+    @Test
+    public void BUG_ISSUE_399_try_some_mocks_with_current_answers() throws Exception {
+        assumeFalse(System.getProperty("java.version").startsWith("1.6")); // Bug in last public HotSpot 1.6
+
+        IMethods iMethods = mock(IMethods.class, withSettings().serializable().defaultAnswer(RETURNS_DEEP_STUBS));
+
+        when(iMethods.iMethodsReturningMethod().linkedListReturningMethod().contains(anyString())).thenReturn(false);
+
+        serializeAndBack(iMethods);
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/ObjectsSerializationTest.java b/src/test/java/org/mockitousage/basicapi/ObjectsSerializationTest.java
new file mode 100644
index 0000000..49c3639
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/ObjectsSerializationTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.io.Serializable;
+
+import static junit.framework.TestCase.assertSame;
+import static org.mockitoutil.SimpleSerializationUtil.serializeAndBack;
+
+@SuppressWarnings("serial")
+public class ObjectsSerializationTest extends TestBase implements Serializable {
+
+    //Ok, this test has nothing to do with mocks but it shows fundamental feature of java serialization that
+    //plays important role in mocking:
+    //Serialization/deserialization actually replaces all instances of serialized object in the object graph (if there are any)
+    //thanks to that mechanizm, stubbing & verification can correctly match method invocations because
+    //one of the parts of invocation matching is checking if mock object is the same
+
+    class Bar implements Serializable {
+        Foo foo;
+    }
+
+    class Foo implements Serializable {
+        Bar bar;
+        Foo() {
+            bar = new Bar();
+            bar.foo = this;
+        }
+    }
+
+    @Test
+    public void shouldSerializationWork() throws Exception {
+        //given
+        Foo foo = new Foo();
+        //when
+        foo = serializeAndBack(foo);
+        //then
+        assertSame(foo, foo.bar.foo);
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/ReplacingObjectMethodsTest.java b/src/test/java/org/mockitousage/basicapi/ReplacingObjectMethodsTest.java
new file mode 100644
index 0000000..19fe43b
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/ReplacingObjectMethodsTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class ReplacingObjectMethodsTest extends TestBase {
+
+    private interface DummyInterface {}
+    private class DummyClass {}
+
+    @Test
+    public void shouldProvideMockyImplementationOfToString() {
+        DummyClass dummyClass = Mockito.mock(DummyClass.class);
+        assertEquals("Mock for DummyClass, hashCode: " + dummyClass.hashCode(), dummyClass.toString());
+        DummyInterface dummyInterface = Mockito.mock(DummyInterface.class);
+        assertEquals("Mock for DummyInterface, hashCode: " + dummyInterface.hashCode(), dummyInterface.toString());
+    }
+
+    @Test
+    public void shouldReplaceObjectMethods() {
+        Object mock = Mockito.mock(ObjectMethodsOverridden.class);
+        Object otherMock = Mockito.mock(ObjectMethodsOverridden.class);
+
+        assertThat(mock).isEqualTo(mock);
+        assertThat(mock).isNotEqualTo(otherMock);
+        assertThat(mock.hashCode()).isNotEqualTo(otherMock.hashCode());
+
+        assertThat(mock.toString()).contains("Mock for ObjectMethodsOverridden");
+    }
+
+    @Test
+    public void shouldReplaceObjectMethodsWhenOverridden() {
+        Object mock = Mockito.mock(ObjectMethodsOverriddenSubclass.class);
+        Object otherMock = Mockito.mock(ObjectMethodsOverriddenSubclass.class);
+
+        assertThat(mock).isEqualTo(mock);
+        assertThat(mock).isNotEqualTo(otherMock);
+        assertThat(mock.hashCode()).isNotEqualTo(otherMock.hashCode());
+
+        assertThat(mock.toString()).contains("Mock for ObjectMethodsOverriddenSubclass");
+    }
+
+    public static class ObjectMethodsOverridden {
+        public boolean equals(Object o) {
+            throw new RuntimeException("Should not be called. MethodInterceptorFilter provides implementation");
+        }
+        public int hashCode() {
+            throw new RuntimeException("Should not be called. MethodInterceptorFilter provides implementation");
+        }
+        public String toString() {
+            throw new RuntimeException("Should not be called. MethodInterceptorFilter provides implementation");
+        }
+    }
+
+    public static class ObjectMethodsOverriddenSubclass extends ObjectMethodsOverridden {
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/ResetInvocationsTest.java b/src/test/java/org/mockitousage/basicapi/ResetInvocationsTest.java
new file mode 100644
index 0000000..53bcf1f
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/ResetInvocationsTest.java
@@ -0,0 +1,52 @@
+package org.mockitousage.basicapi;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+public class ResetInvocationsTest extends TestBase {
+
+    @Mock
+    IMethods methods;
+
+    @Mock
+    IMethods moarMethods;
+
+    @Test
+    public void reset_invocations_should_reset_only_invocations() {
+        when(methods.simpleMethod()).thenReturn("return");
+
+        methods.simpleMethod();
+        verify(methods).simpleMethod();
+
+        clearInvocations(methods);
+
+        verifyNoMoreInteractions(methods);
+        assertEquals("return", methods.simpleMethod());
+    }
+
+    @Test
+    public void should_reset_invocations_on_multiple_mocks() {
+        methods.simpleMethod();
+        moarMethods.simpleMethod();
+
+        clearInvocations(methods, moarMethods);
+
+        verifyNoMoreInteractions(methods, moarMethods);
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void resettingNonMockIsSafe() {
+        clearInvocations("");
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void resettingNullIsSafe() {
+        clearInvocations(new Object[]{null});
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/ResetTest.java b/src/test/java/org/mockitousage/basicapi/ResetTest.java
new file mode 100644
index 0000000..5ec69cc
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/ResetTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.basicapi;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class ResetTest extends TestBase {
+
+    @Mock
+    private IMethods mock;
+
+    @Mock
+    private IMethods mockTwo;
+
+    @Test
+    public void shouldResetOngoingStubbingSoThatMoreMeaningfulExceptionsAreRaised() {
+        mock(IMethods.class);
+        mock.booleanReturningMethod();
+        reset(mock);
+        try {
+            when(null).thenReturn("anything");
+            fail();
+        } catch (MissingMethodInvocationException e) {
+        }
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void resettingNonMockIsSafe() {
+        reset("");
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void resettingNullIsSafe() {
+        reset(new Object[]{null});
+    }
+
+    @Test
+    public void shouldRemoveAllStubbing() throws Exception {
+        when(mock.objectReturningMethod(isA(Integer.class))).thenReturn(100);
+        when(mock.objectReturningMethod(200)).thenReturn(200);
+        reset(mock);
+        assertNull(mock.objectReturningMethod(200));
+        assertEquals("default behavior should return null", null, mock.objectReturningMethod("blah"));
+    }
+
+    @Test
+    public void shouldRemoveAllInteractions() throws Exception {
+        mock.simpleMethod(1);
+        reset(mock);
+        verifyZeroInteractions(mock);
+    }
+
+    @Test
+    public void shouldRemoveStubbingToString() throws Exception {
+        IMethods mockTwo = mock(IMethods.class);
+        when(mockTwo.toString()).thenReturn("test");
+        reset(mockTwo);
+        assertThat(mockTwo.toString()).contains("Mock for IMethods");
+    }
+
+    @Test
+    public void shouldStubbingNotBeTreatedAsInteraction() {
+        when(mock.simpleMethod("one")).thenThrow(new RuntimeException());
+        doThrow(new RuntimeException()).when(mock).simpleMethod("two");
+        reset(mock);
+        verifyZeroInteractions(mock);
+    }
+
+    @Test
+    public void shouldNotAffectMockName() {
+        IMethods mock = mock(IMethods.class, "mockie");
+        IMethods mockTwo = mock(IMethods.class);
+        reset(mock);
+        assertThat(mockTwo.toString()).contains("Mock for IMethods");
+        assertEquals("mockie", "" + mock);
+    }
+
+    @Test
+    public void shouldResetMultipleMocks() {
+        mock.simpleMethod();
+        mockTwo.simpleMethod();
+        reset(mock, mockTwo);
+        verifyNoMoreInteractions(mock, mockTwo);
+    }
+
+    @Test
+    public void shouldValidateStateWhenResetting() {
+        //invalid verify:
+        verify(mock);
+
+        try {
+            reset(mockTwo);
+            fail();
+        } catch (UnfinishedVerificationException e) {
+        }
+    }
+
+    @Test
+    public void shouldMaintainPreviousDefaultAnswer() {
+        //given
+        mock = mock(IMethods.class, RETURNS_MOCKS);
+        //when
+        reset(mock);
+        //then
+        assertNotNull(mock.iMethodsReturningMethod());
+    }
+}
diff --git a/src/test/java/org/mockitousage/basicapi/UsingVarargsTest.java b/src/test/java/org/mockitousage/basicapi/UsingVarargsTest.java
new file mode 100644
index 0000000..3086c54
--- /dev/null
+++ b/src/test/java/org/mockitousage/basicapi/UsingVarargsTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.basicapi;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitoutil.TestBase;
+
+import java.util.ArrayList;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class UsingVarargsTest extends TestBase {
+
+    private interface IVarArgs {
+        void withStringVarargs(int value, String... s);
+        String withStringVarargsReturningString(int value, String... s);
+        void withObjectVarargs(int value, Object... o);
+        boolean withBooleanVarargs(int value, boolean... b);
+        int foo(Object ... objects);
+    }
+
+    @Mock IVarArgs mock;
+
+    @Test
+    public void shouldStubStringVarargs() {
+        when(mock.withStringVarargsReturningString(1)).thenReturn("1");
+        when(mock.withStringVarargsReturningString(2, "1", "2", "3")).thenReturn("2");
+
+        RuntimeException expected = new RuntimeException();
+        doThrow(expected).when(mock).withStringVarargs(3, "1", "2", "3", "4");
+
+        assertEquals("1", mock.withStringVarargsReturningString(1));
+        assertEquals(null, mock.withStringVarargsReturningString(2));
+
+        assertEquals("2", mock.withStringVarargsReturningString(2, "1", "2", "3"));
+        assertEquals(null, mock.withStringVarargsReturningString(2, "1", "2"));
+        assertEquals(null, mock.withStringVarargsReturningString(2, "1", "2", "3", "4"));
+        assertEquals(null, mock.withStringVarargsReturningString(2, "1", "2", "9999"));
+
+        mock.withStringVarargs(3, "1", "2", "3", "9999");
+        mock.withStringVarargs(9999, "1", "2", "3", "4");
+
+        try {
+            mock.withStringVarargs(3, "1", "2", "3", "4");
+            fail();
+        } catch (Exception e) {
+            assertEquals(expected, e);
+        }
+    }
+
+    @Test
+    public void shouldStubBooleanVarargs() {
+        when(mock.withBooleanVarargs(1)).thenReturn(true);
+        when(mock.withBooleanVarargs(1, true, false)).thenReturn(true);
+
+        assertEquals(true, mock.withBooleanVarargs(1));
+        assertEquals(false, mock.withBooleanVarargs(9999));
+
+        assertEquals(true, mock.withBooleanVarargs(1, true, false));
+        assertEquals(false, mock.withBooleanVarargs(1, true, false, true));
+        assertEquals(false, mock.withBooleanVarargs(2, true, false));
+        assertEquals(false, mock.withBooleanVarargs(1, true));
+        assertEquals(false, mock.withBooleanVarargs(1, false, false));
+    }
+
+    @Test
+    public void shouldVerifyStringVarargs() {
+        mock.withStringVarargs(1);
+        mock.withStringVarargs(2, "1", "2", "3");
+        mock.withStringVarargs(3, "1", "2", "3", "4");
+
+        verify(mock).withStringVarargs(1);
+        verify(mock).withStringVarargs(2, "1", "2", "3");
+        try {
+            verify(mock).withStringVarargs(2, "1", "2", "79", "4");
+            fail();
+        } catch (ArgumentsAreDifferent e) {}
+    }
+
+    @Test
+    public void shouldVerifyObjectVarargs() {
+        mock.withObjectVarargs(1);
+        mock.withObjectVarargs(2, "1", new ArrayList<Object>(), new Integer(1));
+        mock.withObjectVarargs(3, new Integer(1));
+
+        verify(mock).withObjectVarargs(1);
+        verify(mock).withObjectVarargs(2, "1", new ArrayList<Object>(), new Integer(1));
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldVerifyBooleanVarargs() {
+        mock.withBooleanVarargs(1);
+        mock.withBooleanVarargs(2, true, false, true);
+        mock.withBooleanVarargs(3, true, true, true);
+
+        verify(mock).withBooleanVarargs(1);
+        verify(mock).withBooleanVarargs(2, true, false, true);
+        try {
+            verify(mock).withBooleanVarargs(3, true, true, true, true);
+            fail();
+        } catch (ArgumentsAreDifferent e) {}
+    }
+
+    @Test
+    public void shouldVerifyWithAnyObject() {
+        Foo foo = Mockito.mock(Foo.class);
+        foo.varArgs("");
+        Mockito.verify(foo).varArgs((String[]) Mockito.anyObject());
+        Mockito.verify(foo).varArgs((String) Mockito.anyObject());
+    }
+
+    @Test
+    public void shouldVerifyWithNullVarArgArray() {
+        Foo foo = Mockito.mock(Foo.class);
+        foo.varArgs((String[]) null);
+        Mockito.verify(foo).varArgs((String[]) Mockito.anyObject());
+        Mockito.verify(foo).varArgs((String[]) null);
+    }
+
+    public class Foo {
+        public void varArgs(String... args) {}
+    }
+
+    interface MixedVarargs {
+        String doSomething(String one, String... varargs);
+        String doSomething(String one, String two, String... varargs);
+    }
+
+    @SuppressWarnings("all")
+    @Test
+    //See bug #31
+    public void shouldStubCorrectlyWhenMixedVarargsUsed() {
+        MixedVarargs mixedVarargs = mock(MixedVarargs.class);
+        when(mixedVarargs.doSomething("hello", (String[])null)).thenReturn("hello");
+        when(mixedVarargs.doSomething("goodbye", (String[])null)).thenReturn("goodbye");
+
+        String result = mixedVarargs.doSomething("hello",(String[]) null);
+        assertEquals("hello", result);
+
+        verify(mixedVarargs).doSomething("hello", (String[])null);
+    }
+
+    @SuppressWarnings("all")
+    @Test
+    public void shouldStubCorrectlyWhenDoubleStringAndMixedVarargsUsed() {
+        MixedVarargs mixedVarargs = mock(MixedVarargs.class);
+        when(mixedVarargs.doSomething("one", "two", (String[])null)).thenReturn("hello");
+        when(mixedVarargs.doSomething("1", "2", (String[])null)).thenReturn("goodbye");
+
+        String result = mixedVarargs.doSomething("one", "two", (String[])null);
+        assertEquals("hello", result);
+    }
+
+    @Test
+    //See bug #157
+    public void shouldMatchEasilyEmptyVararg() throws Exception {
+        //when
+        when(mock.foo(anyVararg())).thenReturn(-1);
+
+        //then
+        assertEquals(-1, mock.foo());
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/AIOOBExceptionWithAtLeastTest.java b/src/test/java/org/mockitousage/bugs/AIOOBExceptionWithAtLeastTest.java
new file mode 100644
index 0000000..58c83f5
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/AIOOBExceptionWithAtLeastTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+//see bug 116
+public class AIOOBExceptionWithAtLeastTest extends TestBase {
+
+    interface IProgressMonitor {
+        void beginTask(String s, int i);
+        void worked(int i);
+        void done();
+    }
+
+    @Test
+    public void testCompleteProgress() throws Exception {
+        IProgressMonitor progressMonitor = mock(IProgressMonitor.class);
+
+        progressMonitor.beginTask("foo", 12);
+        progressMonitor.worked(10);
+        progressMonitor.done();
+
+        verify(progressMonitor).beginTask(anyString(), anyInt());
+        verify(progressMonitor, atLeastOnce()).worked(anyInt());
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ActualInvocationHasNullArgumentNPEBugTest.java b/src/test/java/org/mockitousage/bugs/ActualInvocationHasNullArgumentNPEBugTest.java
new file mode 100644
index 0000000..b0b3c3a
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ActualInvocationHasNullArgumentNPEBugTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class ActualInvocationHasNullArgumentNPEBugTest extends TestBase {
+
+    public interface Fun {
+        String doFun(String something);
+    }
+
+    @Test
+    public void shouldAllowPassingNullArgument() {
+        //given
+        Fun mockFun = mock(Fun.class);
+        when(mockFun.doFun((String) anyObject())).thenReturn("value");
+
+        //when
+        mockFun.doFun(null);
+
+        //then
+        try {
+            verify(mockFun).doFun("hello");
+            fail();
+        } catch(AssertionError r) {
+            //it's ok, we just want to reproduce the bug
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ArgumentCaptorDontCapturePreviouslyVerifiedTest.java b/src/test/java/org/mockitousage/bugs/ArgumentCaptorDontCapturePreviouslyVerifiedTest.java
new file mode 100644
index 0000000..24b6df5
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ArgumentCaptorDontCapturePreviouslyVerifiedTest.java
@@ -0,0 +1,28 @@
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockitousage.IMethods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class ArgumentCaptorDontCapturePreviouslyVerifiedTest {
+    @Test
+    public void previous_verified_invocation_should_still_capture_args() {
+        IMethods mock = mock(IMethods.class);
+
+        mock.oneArg("first");
+        ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
+        verify(mock, times(1)).oneArg(argument.capture());
+        assertThat(argument.getAllValues()).hasSize(1);
+
+        // additional interactions
+        mock.oneArg("second");
+        argument = ArgumentCaptor.forClass(String.class);
+        verify(mock, times(2)).oneArg(argument.capture());
+        assertThat(argument.getAllValues()).hasSize(2);
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/AtLeastMarksAllInvocationsVerified.java b/src/test/java/org/mockitousage/bugs/AtLeastMarksAllInvocationsVerified.java
new file mode 100644
index 0000000..5cefa01
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/AtLeastMarksAllInvocationsVerified.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+// see issue 112
+public class AtLeastMarksAllInvocationsVerified extends TestBase {
+
+    public static class SomeMethods {
+        public void allowedMethod() {
+        }
+        public void disallowedMethod() {
+        }
+    }
+
+    @Test(expected = org.mockito.exceptions.verification.NoInteractionsWanted.class)
+    public void shouldFailBecauseDisallowedMethodWasCalled(){
+        SomeMethods someMethods = mock(SomeMethods.class);
+
+        someMethods.allowedMethod();
+        someMethods.disallowedMethod();
+
+        verify(someMethods, atLeast(1)).allowedMethod();
+        verifyNoMoreInteractions(someMethods);
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/BridgeMethodsHitAgainTest.java b/src/test/java/org/mockitousage/bugs/BridgeMethodsHitAgainTest.java
new file mode 100644
index 0000000..4f356b1
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/BridgeMethodsHitAgainTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockitoutil.TestBase;
+
+import java.io.Serializable;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+//see issue 101
+public class BridgeMethodsHitAgainTest extends TestBase {
+
+  public interface Factory {}
+  public interface ExtendedFactory extends Factory {}
+
+  public interface SomeInterface {
+    Factory factory();
+  }
+
+  public interface SomeSubInterface extends SomeInterface {
+    ExtendedFactory factory();
+  }
+
+  public interface Base<T extends Serializable> {
+    int test(T value);
+  }
+
+  public interface Extended extends Base<String> {
+    @Override
+    int test(String value);
+  }
+
+  @Mock SomeSubInterface someSubInterface;
+  @Mock ExtendedFactory extendedFactory;
+
+  @Test
+  public void basicCheck() {
+    Mockito.when((someSubInterface).factory()).thenReturn(extendedFactory);
+    SomeInterface si = someSubInterface;
+    assertTrue(si.factory() != null);
+  }
+
+  @Test
+  public void checkWithExtraCast() {
+    Mockito.when(((SomeInterface) someSubInterface).factory()).thenReturn(extendedFactory);
+    SomeInterface si = someSubInterface;
+    assertTrue(si.factory() != null);
+  }
+
+    @Test
+    public void testBridgeInvocationIsRecordedForInterceptedMethod() {
+        Extended ext = mock(Extended.class);
+        ext.test("123");
+        verify(ext).test("123");
+        ((Base<String>) ext).test("456");
+        verify(ext).test("456");
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/CaptorAnnotationAutoboxingTest.java b/src/test/java/org/mockitousage/bugs/CaptorAnnotationAutoboxingTest.java
new file mode 100644
index 0000000..d3e9ba6
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/CaptorAnnotationAutoboxingTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+//see issue 188
+public class CaptorAnnotationAutoboxingTest extends TestBase {
+
+    interface Fun {
+        void doFun(double prmitive);
+        void moreFun(int howMuch);
+    }
+
+    @Mock Fun fun;
+    @Captor ArgumentCaptor<Double> captor;
+
+    @Test
+    public void shouldAutoboxSafely() {
+        //given
+        fun.doFun(1.0);
+
+        //then
+        verify(fun).doFun(captor.capture());
+        assertEquals(1.0, captor.getValue());
+    }
+
+    @Captor ArgumentCaptor<Integer> intCaptor;
+
+    @Test
+    public void shouldAutoboxAllPrimitives() {
+        verify(fun, never()).moreFun(intCaptor.capture());
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ClassCastExOnVerifyZeroInteractionsTest.java b/src/test/java/org/mockitousage/bugs/ClassCastExOnVerifyZeroInteractionsTest.java
new file mode 100644
index 0000000..ec0f4d3
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ClassCastExOnVerifyZeroInteractionsTest.java
@@ -0,0 +1,38 @@
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.exceptions.misusing.WrongTypeOfReturnValue;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class ClassCastExOnVerifyZeroInteractionsTest {
+    public interface TestMock {
+        boolean m1();
+    }
+
+    @Test(expected = NoInteractionsWanted.class)
+    public void should_not_throw_ClassCastException_when_mock_verification_fails() {
+        TestMock test = mock(TestMock.class, new Answer<Object>() {
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                return false;
+            }
+        });
+        test.m1();
+        verifyZeroInteractions(test);
+    }
+
+    @Test(expected = WrongTypeOfReturnValue.class)
+    public void should_report_bogus_default_answer() throws Exception {
+        TestMock test = mock(TestMock.class, new Answer<Object>() {
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                return false;
+            }
+        });
+
+        test.toString();
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/CompareMatcherTest.java b/src/test/java/org/mockitousage/bugs/CompareMatcherTest.java
new file mode 100644
index 0000000..5141f26
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/CompareMatcherTest.java
@@ -0,0 +1,131 @@
+package org.mockitousage.bugs;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalMatchers.leq;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.startsWith;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Date;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+
+public class CompareMatcherTest {
+    private static final Object NOT_A_COMPARABLE = new Object();
+
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    public IMethods mock;
+
+    /**
+     * Should not throw an {@link NullPointerException}
+     *
+     * @see Bug-ID https://github.com/mockito/mockito/issues/457
+     */
+    @Test
+    public void compareNullArgument() {
+        final IMethods mock = mock(IMethods.class);
+
+        when(mock.forInteger(leq(5))).thenReturn("");
+
+        assertThat(mock.forInteger(null)).isNull();// a default value must be returned
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToNonCompareable() {
+        when(mock.forObject(leq(5))).thenReturn("");
+
+        assertThat(mock.forObject(NOT_A_COMPARABLE)).isNull();// a default value must be returned
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToNull() {
+        when(mock.forInteger(leq((Integer) null))).thenReturn("");
+
+        assertThat(mock.forInteger(null)).isNull();// a default value must be returned
+    }
+
+    /**
+     * Should not throw an {@link ClassCastException}
+     */
+    @Test
+    public void compareToStringVsInt() {
+        when(mock.forObject(startsWith("Hello"))).thenReturn("");
+
+        assertThat(mock.forObject(123)).isNull();// a default value must be returned
+    }
+
+    @Test
+    public void compareToIntVsString() throws Exception {
+        when(mock.forObject(leq(5))).thenReturn("");
+
+        mock.forObject("abc");
+    }
+
+    @Test
+    public void matchesOverloadsMustBeIgnored() {
+        class TestMatcher implements ArgumentMatcher<Integer> {
+            @Override
+            public boolean matches(Integer arg) {
+                return false;
+            }
+
+            @SuppressWarnings("unused")
+            public boolean matches(Date arg) {
+                throw new UnsupportedOperationException();
+            }
+
+            @SuppressWarnings("unused")
+            public boolean matches(Integer arg, Void v) {
+                throw new UnsupportedOperationException();
+            }
+
+        }
+
+        when(mock.forObject(argThat(new TestMatcher()))).thenReturn("x");
+
+        assertThat(mock.forObject(123)).isNull();
+    }
+
+    @Test
+    public void matchesWithSubTypeExtendingGenericClass() {
+        abstract class GenericMatcher<T> implements ArgumentMatcher<T> {}
+        class TestMatcher extends GenericMatcher<Integer> {
+            @Override
+            public boolean matches(Integer argument) {
+                return false;
+            }
+        }
+        when(mock.forObject(argThat(new TestMatcher()))).thenReturn("x");
+
+        assertThat(mock.forObject(123)).isNull();
+    }
+
+    @Test
+    public void matchesWithSubTypeGenericMethod() {
+        class GenericMatcher<T> implements ArgumentMatcher<T> {
+            @Override
+            public boolean matches(T argument) {
+                return false;
+            }
+        }
+        when(mock.forObject(argThat(new GenericMatcher<Integer>()))).thenReturn("x");
+
+        assertThat(mock.forObject(123)).isNull();
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/ConcurrentModificationExceptionOnMultiThreadedVerificationTest.java b/src/test/java/org/mockitousage/bugs/ConcurrentModificationExceptionOnMultiThreadedVerificationTest.java
new file mode 100644
index 0000000..bc52c41
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ConcurrentModificationExceptionOnMultiThreadedVerificationTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.mockito.Mockito.*;
+
+// issue 322
+// the only evidence of this failing test was shown on a RHEL with IBM J9 JVM 64bits
+//
+// details
+// java.fullversion=JRE 1.6.0 IBM J9 2.6 Linux amd64-64 20111113_94967  (JIT enabled, AOT enabled)
+// Linux2.6.32-220.4.2.el6.x86_64 #1SMP Mon Feb 6 16:39:28EST 2012x86_64 x86_64 x86_64 GNU/Linux
+public class ConcurrentModificationExceptionOnMultiThreadedVerificationTest {
+
+    int nThreads = 1;
+
+    static final int TIMES = 100;
+    static final int INTERVAL_MILLIS = 10;
+
+    ITarget target = Mockito.mock(ITarget.class);
+    ExecutorService fixedThreadPool;
+
+    @Before
+    public void setUp() {
+        target = Mockito.mock(ITarget.class);
+        fixedThreadPool = Executors.newFixedThreadPool(nThreads);
+    }
+
+    @Test
+    public void shouldSuccessfullyVerifyConcurrentInvocationsWithTimeout() throws Exception {
+        int potentialOverhead = 1000; // Leave 1000ms extra before timing out as leeway for test overheads
+        int expectedMaxTestLength = TIMES * INTERVAL_MILLIS + potentialOverhead;
+
+        reset(target);
+        startInvocations();
+
+        verify(target, timeout(expectedMaxTestLength).times(TIMES * nThreads)).targetMethod("arg");
+        verifyNoMoreInteractions(target);
+    }
+
+    private void startInvocations() throws InterruptedException,
+            ExecutionException {
+
+        for(int i=0; i<nThreads; i++) {
+            fixedThreadPool.submit(new TargetInvoker(i));
+        }
+
+    }
+
+    public class TargetInvoker implements Callable<Object> {
+        private final int seq;
+
+        TargetInvoker(int seq) {
+            this.seq = seq;
+        }
+
+        public Object call() throws Exception {
+            System.err.println("started " + seq);
+            for (int i = 0; i < TIMES; i++) {
+                Thread.yield();
+                target.targetMethod("arg");
+                Thread.sleep((long) INTERVAL_MILLIS);
+            }
+            System.err.println("finished" + seq);
+            return seq;
+        }
+
+    }
+
+    public interface ITarget {
+        String targetMethod(String arg);
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/ConfusedSignatureTest.java b/src/test/java/org/mockitousage/bugs/ConfusedSignatureTest.java
new file mode 100644
index 0000000..1a3c6b1
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ConfusedSignatureTest.java
@@ -0,0 +1,45 @@
+package org.mockitousage.bugs;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+
+public class ConfusedSignatureTest {
+
+    @Test
+    public void should_mock_method_which_has_generic_return_type_in_superclass_and_concrete_one_in_interface() {
+        Sub mock = mock(Sub.class);
+        // The following line resulted in
+        // org.mockito.exceptions.misusing.MissingMethodInvocationException:
+        // when() requires an argument which has to be 'a method call on a mock'.
+        // Presumably confused by the interface/superclass signatures.
+        when(mock.getFoo()).thenReturn("Hello");
+
+        assertThat(mock.getFoo()).isEqualTo("Hello");
+    }
+
+    public class Super<T> {
+        private T value;
+
+        public Super(T value) {
+            this.value = value;
+        }
+
+        public T getFoo() { return value; }
+    }
+
+    public class Sub
+            extends Super<String>
+            implements iInterface {
+
+        public Sub(String s) {
+            super(s);
+        }
+    }
+
+    public interface iInterface {
+        String getFoo();
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/CovariantOverrideTest.java b/src/test/java/org/mockitousage/bugs/CovariantOverrideTest.java
new file mode 100644
index 0000000..1248d92
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/CovariantOverrideTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+//see issue 101
+public class CovariantOverrideTest extends TestBase {
+
+    public interface ReturnsObject {
+
+        Object callMe();
+    }
+
+    public interface ReturnsString extends ReturnsObject {
+
+        // Java 5 covariant override of method from parent interface
+        String callMe();
+    }
+
+    @Test
+    public void returnFoo1() {
+        ReturnsObject mock = mock(ReturnsObject.class);
+        when(mock.callMe()).thenReturn("foo");
+        assertEquals("foo", mock.callMe()); // Passes
+    }
+
+    @Test
+    public void returnFoo2() {
+        ReturnsString mock = mock(ReturnsString.class);
+        when(mock.callMe()).thenReturn("foo");
+        assertEquals("foo", mock.callMe()); // Passes
+    }
+
+    @Test
+    public void returnFoo3() {
+        ReturnsObject mock = mock(ReturnsString.class);
+        when(mock.callMe()).thenReturn("foo");
+        assertEquals("foo", mock.callMe()); // Passes
+    }
+
+    @Test
+    public void returnFoo4() {
+        ReturnsString mock = mock(ReturnsString.class);
+        mock.callMe(); // covariant override not generated
+        ReturnsObject mock2 = mock; // Switch to base type to call covariant override
+        verify(mock2).callMe(); // Fails: java.lang.AssertionError: expected:<foo> but was:<null>
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/DiamondInheritanceIsConfusingMockitoTest.java b/src/test/java/org/mockitousage/bugs/DiamondInheritanceIsConfusingMockitoTest.java
new file mode 100644
index 0000000..c6e12a1
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/DiamondInheritanceIsConfusingMockitoTest.java
@@ -0,0 +1,44 @@
+package org.mockitousage.bugs;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+// see #508
+public class DiamondInheritanceIsConfusingMockitoTest {
+
+    @Test
+    public void should_work() {
+        Sub mock = Mockito.mock(Sub.class);
+        // The following line results in
+        // org.mockito.exceptions.misusing.MissingMethodInvocationException:
+        // when() requires an argument which has to be 'a method call on a mock'.
+        // Presumably confused by the interface/superclass signatures.
+        Mockito.when(mock.getFoo()).thenReturn("Hello");
+
+        Assert.assertEquals("Hello", mock.getFoo());
+    }
+
+    public class Super<T> {
+        private T value;
+
+        public Super(T value) {
+            this.value = value;
+        }
+
+        public T getFoo() { return value; }
+    }
+
+    public class Sub
+            extends Super<String>
+            implements iInterface {
+
+        public Sub(String s) {
+            super(s);
+        }
+    }
+
+    public interface iInterface {
+        String getFoo();
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/EqualsWithDeltaTest.java b/src/test/java/org/mockitousage/bugs/EqualsWithDeltaTest.java
new file mode 100644
index 0000000..f84bfed
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/EqualsWithDeltaTest.java
@@ -0,0 +1,40 @@
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.EqualsWithDelta;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EqualsWithDeltaTest {
+
+    @Test
+    public void testEqualsWithDelta_NullExpected() throws Exception {
+        ArgumentMatcher<Number> matcher = equalsWithDelta(null);
+        assertThat(matcher.matches(1.0)).isFalse();
+    }
+
+    @Test
+    public void testEqualsWithDelta_NullActual() throws Exception {
+        ArgumentMatcher<Number> matcher = equalsWithDelta(1.0);
+        assertThat(matcher.matches(null)).isFalse();
+    }
+
+    @Test
+    public void testEqualsWithDelta_NullActualAndExpected() throws Exception {
+        ArgumentMatcher<Number> matcher = equalsWithDelta(null);
+        assertThat(matcher.matches(null)).isTrue();
+    }
+
+    @Test
+    public void testEqualsWithDelta_WhenActualAndExpectedAreTheSameObject() throws Exception {
+        Double expected = 1.0;
+        Double actual = expected;
+        ArgumentMatcher<Number> matcher = equalsWithDelta(expected);
+        assertThat(matcher.matches(actual)).isTrue();
+    }
+
+    public ArgumentMatcher<Number> equalsWithDelta(final Double expected) {
+        return new EqualsWithDelta(expected, .000001);
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/FinalHashCodeAndEqualsRaiseNPEInInitMocksTest.java b/src/test/java/org/mockitousage/bugs/FinalHashCodeAndEqualsRaiseNPEInInitMocksTest.java
new file mode 100644
index 0000000..e6c82cf
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/FinalHashCodeAndEqualsRaiseNPEInInitMocksTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.nio.charset.Charset;
+
+// issue 327
+public class FinalHashCodeAndEqualsRaiseNPEInInitMocksTest {
+    @Mock private Charset charset;
+    @InjectMocks private FieldCharsetHolder fieldCharsetHolder;
+    @InjectMocks private ConstructorCharsetHolder constructorCharsetHolder;
+
+    @Test
+    public void dont_raise_NullPointerException() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    private static class FieldCharsetHolder {
+        private Charset charset;
+    }
+
+    private static class ConstructorCharsetHolder {
+        public ConstructorCharsetHolder(Charset charset) {
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/IOOBExceptionShouldNotBeThrownWhenNotCodingFluentlyTest.java b/src/test/java/org/mockitousage/bugs/IOOBExceptionShouldNotBeThrownWhenNotCodingFluentlyTest.java
new file mode 100644
index 0000000..7d47a64
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/IOOBExceptionShouldNotBeThrownWhenNotCodingFluentlyTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.stubbing.OngoingStubbing;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class IOOBExceptionShouldNotBeThrownWhenNotCodingFluentlyTest {
+
+    @Test
+    public void second_stubbing_throws_IndexOutOfBoundsException() throws Exception {
+
+        @SuppressWarnings("unchecked")
+        Map<String, String> map = mock(Map.class);
+
+        OngoingStubbing<String> mapOngoingStubbing = when(map.get(anyString()));
+
+        mapOngoingStubbing.thenReturn("first stubbing");
+
+        try {
+            mapOngoingStubbing.thenReturn("second stubbing");
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.getMessage())
+                    .contains("Incorrect use of API detected here")
+                    .contains(this.getClass().getSimpleName());
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ImplementationOfGenericAbstractMethodNotInvokedOnSpyTest.java b/src/test/java/org/mockitousage/bugs/ImplementationOfGenericAbstractMethodNotInvokedOnSpyTest.java
new file mode 100644
index 0000000..a2498e9
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ImplementationOfGenericAbstractMethodNotInvokedOnSpyTest.java
@@ -0,0 +1,30 @@
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.spy;
+
+public class ImplementationOfGenericAbstractMethodNotInvokedOnSpyTest {
+    public abstract class GenericAbstract<T> {
+        protected abstract String method_to_implement(T value);
+
+        public String public_method(T value) {
+            return method_to_implement(value);
+        }
+    }
+
+    public class ImplementsGenericMethodOfAbstract<T extends Number> extends GenericAbstract<T> {
+        @Override
+        protected String method_to_implement(T value) {
+            return "concrete value";
+        }
+    }
+
+    @Test
+    public void should_invoke_method_to_implement() {
+        GenericAbstract<Number> spy = spy(new ImplementsGenericMethodOfAbstract<Number>());
+
+        assertThat(spy.public_method(73L)).isEqualTo("concrete value");
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/InheritedGenericsPolimorphicCallTest.java b/src/test/java/org/mockitousage/bugs/InheritedGenericsPolimorphicCallTest.java
new file mode 100644
index 0000000..02eb099
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/InheritedGenericsPolimorphicCallTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.verify;
+
+@SuppressWarnings("unchecked")
+//see issue 200
+public class InheritedGenericsPolimorphicCallTest extends TestBase {
+
+    protected interface MyIterable<T> extends Iterable<T> {
+        MyIterator<T> iterator();
+    }
+
+    protected interface MyIterator<T> extends Iterator<T> {
+        // adds nothing here
+    }
+
+    MyIterator<String> myIterator = Mockito.mock(MyIterator.class);
+    MyIterable<String> iterable = Mockito.mock(MyIterable.class);
+
+    @Test
+    public void shouldStubbingWork() {
+        Mockito.when(iterable.iterator()).thenReturn(myIterator);
+        Assert.assertNotNull(((Iterable<String>) iterable).iterator());
+        Assert.assertNotNull(iterable.iterator());
+    }
+
+    @Test
+    public void shouldVerificationWorks() {
+        iterable.iterator();
+
+        verify(iterable).iterator();
+        verify((Iterable<String>) iterable).iterator();
+    }
+
+    @Test
+    public void shouldWorkExactlyAsJavaProxyWould() {
+        //given
+        final List<Method> methods = new LinkedList<Method>();
+        InvocationHandler handler = new InvocationHandler() {
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            methods.add(method);
+            return null;
+        }};
+
+        iterable = (MyIterable<String>) Proxy.newProxyInstance(
+                this.getClass().getClassLoader(),
+                new Class<?>[] { MyIterable.class },
+                handler);
+
+        //when
+        iterable.iterator();
+        ((Iterable<String>) iterable).iterator();
+
+        //then
+        assertEquals(2, methods.size());
+        assertEquals(methods.get(0), methods.get(1));
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ListenersLostOnResetMockTest.java b/src/test/java/org/mockitousage/bugs/ListenersLostOnResetMockTest.java
new file mode 100644
index 0000000..61a5268
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ListenersLostOnResetMockTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+
+import org.junit.Test;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.listeners.MethodInvocationReport;
+
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+public class ListenersLostOnResetMockTest {
+
+    @Test
+    public void listener() throws Exception {
+        InvocationListener invocationListener = mock(InvocationListener.class);
+
+        List mockedList = mock(List.class, withSettings().invocationListeners(invocationListener));
+        reset(mockedList);
+
+        mockedList.clear();
+
+        verify(invocationListener).reportInvocation(any(MethodInvocationReport.class));
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/MockitoRunnerBreaksWhenNoTestMethodsTest.java b/src/test/java/org/mockitousage/bugs/MockitoRunnerBreaksWhenNoTestMethodsTest.java
new file mode 100644
index 0000000..e70eb7e
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/MockitoRunnerBreaksWhenNoTestMethodsTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import org.junit.Test;
+import org.junit.internal.TextListener;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+
+// @Ignore("for demo only. this test cannot be enabled as it fails :)")
+public class MockitoRunnerBreaksWhenNoTestMethodsTest extends TestBase {
+
+    @Test
+    public void ensure_the_test_runner_breaks() throws Exception {
+        JUnitCore runner = new JUnitCore();
+//        runner.addListener(new TextListener(System.out));
+        runner.addListener(new TextListener(DevNull.out));
+
+        Result result = runner.run(TestClassWithoutTestMethod.class);
+
+        assertEquals(1, result.getFailureCount());
+        assertTrue(result.getFailures().get(0).getException() instanceof MockitoException);
+        assertFalse(result.wasSuccessful());
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    static class TestClassWithoutTestMethod { // package visibility is important
+        public void notATestMethod() { }
+    }
+
+    public static final class DevNull {
+        public final static PrintStream out = new PrintStream(new OutputStream() {
+            public void close() {}
+            public void flush() {}
+            public void write(byte[] b) {}
+            public void write(byte[] b, int off, int len) {}
+            public void write(int b) {}
+
+        } );
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/MultipleInOrdersTest.java b/src/test/java/org/mockitousage/bugs/MultipleInOrdersTest.java
new file mode 100644
index 0000000..41bde29
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/MultipleInOrdersTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+
+import java.util.List;
+
+import static org.junit.Assert.assertNotSame;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+
+@SuppressWarnings("unchecked")
+public class MultipleInOrdersTest {
+
+    @Test
+    public void inOrderTest(){
+        List<String> list= mock(List.class);
+
+        list.add("a");
+        list.add("x");
+        list.add("b");
+        list.add("y");
+
+        InOrder inOrder = inOrder(list);
+        InOrder inAnotherOrder = inOrder(list);
+        assertNotSame(inOrder, inAnotherOrder);
+
+        inOrder.verify(list).add("a");
+        inOrder.verify(list).add("b");
+
+        inAnotherOrder.verify(list).add("x");
+        inAnotherOrder.verify(list).add("y");
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/MultithreadedStubbingHalfManualTest.java b/src/test/java/org/mockitousage/bugs/MultithreadedStubbingHalfManualTest.java
new file mode 100644
index 0000000..c0549b3
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/MultithreadedStubbingHalfManualTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+
+import static java.util.Collections.synchronizedList;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Ignore
+public class MultithreadedStubbingHalfManualTest {
+
+    /**
+     * Class with two methods, one of them is repeatedly mocked while another is repeatedly called.
+     */
+    public interface ToMock {
+        Integer getValue(Integer param);
+
+        List<Integer> getValues(Integer param);
+    }
+
+    /**
+     * Thread pool for concurrent invocations.
+     */
+    private Executor executor;
+
+    private List<Exception> exceptions = synchronizedList(new LinkedList<Exception>());
+
+    @Before
+    public void setUp() {
+        this.executor = Executors.newSingleThreadExecutor();
+    }
+
+    /**
+     * The returned runnable simply calls ToMock.getValues(int).
+     *
+     * @param toMock The mocked object
+     * @return The runnable.
+     */
+    private Runnable getConflictingRunnable(final ToMock toMock) {
+        return new Runnable() {
+            public void run() {
+                while (true) {
+                    try {
+                        Thread.sleep((long) (Math.random() * 10));
+                    } catch (InterruptedException e) {
+                    }
+                    if (!toMock.getValues(0).isEmpty()) {
+                        fail("Shouldn't happen, were just making sure it wasn't optimized away...");
+                    }
+                }
+            }
+        };
+    }
+
+    @Test
+    //this problem shows at 4 out of 5 executions
+    //it is not strictly a bug because Mockito does not support simultanous stubbing (see FAQ)
+    //however I decided to synchronize some calls in order to make the exceptions nicer
+    public void tryToRevealTheProblem() {
+        ToMock toMock = mock(ToMock.class);
+        for (int i = 0; i < 100; i++) {
+            int j = i % 11;
+
+            // Repeated mocking
+            when(toMock.getValue(i)).thenReturn(j);
+            //TODO make it also showing errors for doReturn()
+//            doReturn(j).when(toMock).getValue(i);
+
+            while (true) {
+                try {
+                    // Scheduling invocation
+                    this.executor.execute(getConflictingRunnable(toMock));
+                    break;
+                } catch (RejectedExecutionException ex) {
+                    fail();
+                }
+            }
+
+            try {
+                Thread.sleep(10 / ((i % 10) + 1)); //NOPMD
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/NPEOnAnyClassMatcherAutounboxTest.java b/src/test/java/org/mockitousage/bugs/NPEOnAnyClassMatcherAutounboxTest.java
new file mode 100644
index 0000000..b047a08
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/NPEOnAnyClassMatcherAutounboxTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+//see issue 221
+public class NPEOnAnyClassMatcherAutounboxTest extends TestBase {
+
+    interface Foo {
+        void bar(long id);
+    }
+
+    @Test
+    public void shouldNotThrowNPE() {
+        Foo f = mock(Foo.class);
+        f.bar(1);
+        verify(f).bar(any(Long.class));
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/NPEWhenCustomExceptionStackTraceReturnNullTest.java b/src/test/java/org/mockitousage/bugs/NPEWhenCustomExceptionStackTraceReturnNullTest.java
new file mode 100644
index 0000000..50acbad
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/NPEWhenCustomExceptionStackTraceReturnNullTest.java
@@ -0,0 +1,32 @@
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.when;
+
+public class NPEWhenCustomExceptionStackTraceReturnNullTest extends TestBase {
+
+    @Mock
+    IMethods mock;
+
+    class NullStackTraceException extends RuntimeException {
+        @Override
+        public Exception fillInStackTrace() {
+            return null;
+        }
+    }
+
+    //issue 866
+    @Test
+    public void shouldNotThrowNPE() {
+        when(mock.simpleMethod()).thenThrow(new NullStackTraceException());
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch(NullStackTraceException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/NPEWhenMockingThrowablesTest.java b/src/test/java/org/mockitousage/bugs/NPEWhenMockingThrowablesTest.java
new file mode 100644
index 0000000..3884319
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/NPEWhenMockingThrowablesTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.when;
+
+public class NPEWhenMockingThrowablesTest extends TestBase {
+
+    @Mock IMethods mock;
+    @Mock DummyException mock2;
+
+    class DummyException extends RuntimeException {
+        private static final long serialVersionUID = 1L;
+    }
+
+    //issue 70
+    @Test
+    public void shouldNotThrowNPE() {
+        when(mock.simpleMethod()).thenThrow(mock2);
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch(DummyException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/NPEWithCertainMatchersTest.java b/src/test/java/org/mockitousage/bugs/NPEWithCertainMatchersTest.java
new file mode 100644
index 0000000..d1475d0
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/NPEWithCertainMatchersTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+public class NPEWithCertainMatchersTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @After
+    public void clearState() {
+        this.resetState();
+    }
+
+    @Test
+    public void shouldNotThrowNPEWhenIntegerPassed() {
+        mock.intArgumentMethod(100);
+
+        verify(mock).intArgumentMethod(isA(Integer.class));
+    }
+
+    @Test
+    public void shouldNotThrowNPEWhenIntPassed() {
+        mock.intArgumentMethod(100);
+
+        verify(mock).intArgumentMethod(isA(Integer.class));
+    }
+
+    @Test
+    public void shouldNotThrowNPEWhenIntegerPassedToEq() {
+        mock.intArgumentMethod(100);
+
+        verify(mock).intArgumentMethod(eq(new Integer(100)));
+    }
+
+    @Test
+    public void shouldNotThrowNPEWhenIntegerPassedToSame() {
+        mock.intArgumentMethod(100);
+
+        verify(mock, never()).intArgumentMethod(same(new Integer(100)));
+    }
+
+    @Test(expected = AssertionError.class)
+    public void shouldNotThrowNPEWhenNullPassedToEq() {
+        mock.objectArgMethod("not null");
+
+        verify(mock).objectArgMethod(eq(null));
+    }
+
+    @Test(expected = AssertionError.class)
+    public void shouldNotThrowNPEWhenNullPassedToSame() {
+        mock.objectArgMethod("not null");
+
+        verify(mock).objectArgMethod(same(null));
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ShouldMocksCompareToBeConsistentWithEqualsTest.java b/src/test/java/org/mockitousage/bugs/ShouldMocksCompareToBeConsistentWithEqualsTest.java
new file mode 100644
index 0000000..97052ba
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ShouldMocksCompareToBeConsistentWithEqualsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.util.Date;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+//see issue 184
+public class ShouldMocksCompareToBeConsistentWithEqualsTest extends TestBase {
+
+    @Test
+    public void should_compare_to_be_consistent_with_equals() {
+        //given
+        Date today    = mock(Date.class);
+        Date tomorrow = mock(Date.class);
+
+        //when
+        Set<Date> set = new TreeSet<Date>();
+        set.add(today);
+        set.add(tomorrow);
+
+        //then
+        assertEquals(2, set.size());
+    }
+
+    @Test
+    public void should_compare_to_be_consistent_with_equals_when_comparing_the_same_reference() {
+        //given
+        Date today    = mock(Date.class);
+
+        //when
+        Set<Date> set = new TreeSet<Date>();
+        set.add(today);
+        set.add(today);
+
+        //then
+        assertEquals(1, set.size());
+    }
+
+    @Test
+    public void should_allow_stubbing_and_verifying_compare_to() {
+        //given
+        Date mock    = mock(Date.class);
+        when(mock.compareTo(any(Date.class))).thenReturn(10);
+
+        //when
+        mock.compareTo(new Date());
+
+        //then
+        assertEquals(10, mock.compareTo(new Date()));
+        verify(mock, atLeastOnce()).compareTo(any(Date.class));
+    }
+
+    @Test
+    public void should_reset_not_remove_default_stubbing() {
+        //given
+        Date mock    = mock(Date.class);
+        reset(mock);
+
+        //then
+        assertEquals(1, mock.compareTo(new Date()));
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/ShouldNotDeadlockAnswerExecutionTest.java b/src/test/java/org/mockitousage/bugs/ShouldNotDeadlockAnswerExecutionTest.java
new file mode 100644
index 0000000..0b9ef35
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ShouldNotDeadlockAnswerExecutionTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+//see bug 190
+public class ShouldNotDeadlockAnswerExecutionTest {
+
+    @Test
+    public void failIfMockIsSharedBetweenThreads() throws Exception {
+        Service service = Mockito.mock(Service.class);
+        ExecutorService threads = Executors.newCachedThreadPool();
+        AtomicInteger counter = new AtomicInteger(2);
+
+        // registed answer on verySlowMethod
+
+        Mockito.when(service.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
+
+        // execute verySlowMethod twice in separate threads
+
+        threads.execute(new ServiceRunner(service));
+        threads.execute(new ServiceRunner(service));
+
+        // waiting for threads to finish
+
+        threads.shutdown();
+
+        if (!threads.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
+            // threads were timed-out
+            Assert.fail();
+        }
+    }
+
+    @Test
+    public void successIfEveryThreadHasItsOwnMock() throws Exception {
+        Service service1 = Mockito.mock(Service.class);
+        Service service2 = Mockito.mock(Service.class);
+        ExecutorService threads = Executors.newCachedThreadPool();
+        AtomicInteger counter = new AtomicInteger(2);
+
+        // registed answer on verySlowMethod
+
+        Mockito.when(service1.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
+        Mockito.when(service2.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
+
+        // execute verySlowMethod twice in separate threads
+
+        threads.execute(new ServiceRunner(service1));
+        threads.execute(new ServiceRunner(service2));
+
+        // waiting for threads to finish
+
+        threads.shutdown();
+
+        if (!threads.awaitTermination(500, TimeUnit.MILLISECONDS)) {
+            // threads were timed-out
+            Assert.fail();
+        }
+    }
+
+    static class LockingAnswer implements Answer<String> {
+
+        private AtomicInteger counter;
+
+        public LockingAnswer(AtomicInteger counter) {
+            this.counter = counter;
+        }
+
+        /**
+         * Decrement counter and wait until counter has value 0
+         */
+        public String answer(InvocationOnMock invocation) throws Throwable {
+            counter.decrementAndGet();
+
+            while (counter.get() != 0) {
+                Thread.sleep(10);
+            }
+
+            return null;
+        }
+
+    }
+
+    static class ServiceRunner implements Runnable {
+
+        private Service service;
+
+        public ServiceRunner(Service service) {
+            this.service = service;
+        }
+
+        public void run() {
+            service.verySlowMethod();
+        }
+
+    }
+
+    interface Service {
+
+        String verySlowMethod();
+
+    }
+
+}
+
diff --git a/src/test/java/org/mockitousage/bugs/ShouldOnlyModeAllowCapturingArgumentsTest.java b/src/test/java/org/mockitousage/bugs/ShouldOnlyModeAllowCapturingArgumentsTest.java
new file mode 100644
index 0000000..8b835e7
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/ShouldOnlyModeAllowCapturingArgumentsTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.only;
+import static org.mockito.Mockito.verify;
+
+//bug 197
+public class ShouldOnlyModeAllowCapturingArgumentsTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @Test
+    public void shouldAllowCapturingArguments() {
+        //given
+        mock.simpleMethod("o");
+        ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);
+
+        //when
+        verify(mock, only()).simpleMethod(arg.capture());
+
+        //then
+        assertEquals("o", arg.getValue());
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/SpyShouldHaveNiceNameTest.java b/src/test/java/org/mockitousage/bugs/SpyShouldHaveNiceNameTest.java
new file mode 100644
index 0000000..5546f2d
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/SpyShouldHaveNiceNameTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.Spy;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.verify;
+
+//see issue 216
+public class SpyShouldHaveNiceNameTest extends TestBase {
+
+    @Spy List<Integer> veryCoolSpy = new LinkedList<Integer>();
+
+    @Test
+    public void shouldPrintNiceName() {
+        //when
+        veryCoolSpy.add(1);
+
+        try {
+            verify(veryCoolSpy).add(2);
+            fail();
+        } catch(AssertionError e) {
+            Assertions.assertThat(e.getMessage()).contains("veryCoolSpy");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/StubbingMocksThatAreConfiguredToReturnMocksTest.java b/src/test/java/org/mockitousage/bugs/StubbingMocksThatAreConfiguredToReturnMocksTest.java
new file mode 100644
index 0000000..bc31297
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/StubbingMocksThatAreConfiguredToReturnMocksTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+//issue 151
+public class StubbingMocksThatAreConfiguredToReturnMocksTest extends TestBase {
+
+    @Test
+    public void shouldAllowStubbingMocksConfiguredWithRETURNS_MOCKS() {
+        IMethods mock = mock(IMethods.class, RETURNS_MOCKS);
+        when(mock.objectReturningMethodNoArgs()).thenReturn(null);
+    }
+
+    @Test
+    public void shouldAllowStubbingMocksConfiguredWithRETURNS_MOCKSWithDoApi() {
+        IMethods mock = mock(IMethods.class, RETURNS_MOCKS);
+        doReturn(null).when(mock).objectReturningMethodNoArgs();
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/VerifyingWithAnExtraCallToADifferentMockTest.java b/src/test/java/org/mockitousage/bugs/VerifyingWithAnExtraCallToADifferentMockTest.java
new file mode 100644
index 0000000..9aa7128
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/VerifyingWithAnExtraCallToADifferentMockTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.NeverWantedButInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+//see bug 138
+public class VerifyingWithAnExtraCallToADifferentMockTest extends TestBase {
+
+    @Mock IMethods mock;
+    @Mock IMethods mockTwo;
+
+    @Test
+    public void shouldAllowVerifyingWhenOtherMockCallIsInTheSameLine() {
+        //given
+        when(mock.otherMethod()).thenReturn("foo");
+
+        //when
+        mockTwo.simpleMethod("foo");
+
+        //then
+        verify(mockTwo).simpleMethod(mock.otherMethod());
+        try {
+            verify(mockTwo, never()).simpleMethod(mock.otherMethod());
+            fail();
+        } catch (NeverWantedButInvoked e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/creation/ConstructorInvokingMethodShouldNotRaiseExceptionTest.java b/src/test/java/org/mockitousage/bugs/creation/ConstructorInvokingMethodShouldNotRaiseExceptionTest.java
new file mode 100644
index 0000000..787f729
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/creation/ConstructorInvokingMethodShouldNotRaiseExceptionTest.java
@@ -0,0 +1,67 @@
+package org.mockitousage.bugs.creation;
+
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import java.util.Random;
+
+@RunWith(Enclosed.class)
+public class ConstructorInvokingMethodShouldNotRaiseExceptionTest {
+
+    public static class WithDumbMethod {
+        @Spy
+        HasConstructorInvokingMethod hasConstructorInvokingMethod;
+
+        @Test
+        public void should_be_able_to_create_spy() throws Exception {
+            MockitoAnnotations.initMocks(this);
+        }
+
+        private static class HasConstructorInvokingMethod {
+            public HasConstructorInvokingMethod() { someMethod(); }
+
+            void someMethod() { }
+        }
+    }
+
+    public static class UsingMethodObjectReferenceResult {
+        @Spy
+        HasConstructorInvokingMethod hasConstructorInvokingMethod;
+
+        @Test
+        public void should_be_able_to_create_spy() throws Exception {
+            MockitoAnnotations.initMocks(this);
+        }
+
+        private static class HasConstructorInvokingMethod {
+            private final boolean doesIt;
+            public HasConstructorInvokingMethod() {
+                doesIt = someMethod().contains("yup");
+            }
+
+            String someMethod() { return "tada!"; }
+        }
+    }
+
+    public static class UsingMethodPrimitiveResult {
+        @Spy
+        HasConstructorInvokingMethod hasConstructorInvokingMethod;
+
+        @Test
+        public void should_be_able_to_create_spy() throws Exception {
+            MockitoAnnotations.initMocks(this);
+        }
+
+        private static class HasConstructorInvokingMethod {
+            private final boolean doesIt;
+            public HasConstructorInvokingMethod() {
+                doesIt = someMethod();
+            }
+
+            boolean someMethod() { return new Random().nextBoolean(); }
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/creation/PublicMethodInParentWithNonPublicTypeInSignatureTest.java b/src/test/java/org/mockitousage/bugs/creation/PublicMethodInParentWithNonPublicTypeInSignatureTest.java
new file mode 100644
index 0000000..9d4e340
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/creation/PublicMethodInParentWithNonPublicTypeInSignatureTest.java
@@ -0,0 +1,22 @@
+package org.mockitousage.bugs.creation;
+
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockitousage.bugs.creation.api.PublicClass;
+
+// see GH-233
+public class PublicMethodInParentWithNonPublicTypeInSignatureTest {
+
+    private Object ref;
+
+    @Test
+    public void java_object_creation() throws Exception {
+        ref = new PublicClass();
+    }
+
+    @Test
+    public void should_not_fail_when_instantiating() throws Exception {
+        ref = Mockito.mock(PublicClass.class);
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/creation/ShouldAllowInlineMockCreationTest.java b/src/test/java/org/mockitousage/bugs/creation/ShouldAllowInlineMockCreationTest.java
new file mode 100644
index 0000000..ff46844
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/creation/ShouldAllowInlineMockCreationTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs.creation;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+//see issue 191
+public class ShouldAllowInlineMockCreationTest extends TestBase {
+
+    @Mock List list;
+
+    @Test
+    public void shouldAllowInlineMockCreation() {
+        when(list.get(0)).thenReturn(mock(Set.class));
+        assertTrue(list.get(0) instanceof Set);
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/creation/api/PublicClass.java b/src/test/java/org/mockitousage/bugs/creation/api/PublicClass.java
new file mode 100644
index 0000000..243036a
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/creation/api/PublicClass.java
@@ -0,0 +1,6 @@
+package org.mockitousage.bugs.creation.api;
+
+import org.mockitousage.bugs.creation.otherpackage.PublicParentClass;
+
+public class PublicClass extends PublicParentClass {
+}
diff --git a/src/test/java/org/mockitousage/bugs/creation/otherpackage/PublicParentClass.java b/src/test/java/org/mockitousage/bugs/creation/otherpackage/PublicParentClass.java
new file mode 100644
index 0000000..8f560d4
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/creation/otherpackage/PublicParentClass.java
@@ -0,0 +1,6 @@
+package org.mockitousage.bugs.creation.otherpackage;
+
+public class PublicParentClass {
+    public void method_with_non_public_argument(PackageLocalArg arg) { }
+    static class PackageLocalArg { }
+}
diff --git a/src/test/java/org/mockitousage/bugs/deepstubs/DeepStubFailingWhenGenericNestedAsRawTypeTest.java b/src/test/java/org/mockitousage/bugs/deepstubs/DeepStubFailingWhenGenericNestedAsRawTypeTest.java
new file mode 100644
index 0000000..cbc660d
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/deepstubs/DeepStubFailingWhenGenericNestedAsRawTypeTest.java
@@ -0,0 +1,26 @@
+package org.mockitousage.bugs.deepstubs;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.*;
+
+public class DeepStubFailingWhenGenericNestedAsRawTypeTest {
+
+  interface MyClass1<MC2 extends MyClass2> {
+    MC2 getNested();
+  }
+
+  interface MyClass2<MC3 extends MyClass3> {
+    MC3 getNested();
+  }
+
+  interface MyClass3 {
+    String returnSomething();
+  }
+
+  @Test
+  public void discoverDeepMockingOfGenerics() {
+    MyClass1 myMock1 = mock(MyClass1.class, RETURNS_DEEP_STUBS);
+    when(myMock1.getNested().getNested().returnSomething()).thenReturn("Hello World.");
+  }
+}
diff --git a/src/test/java/org/mockitousage/bugs/deepstubs/DeepStubsWronglyReportsSerializationProblemsTest.java b/src/test/java/org/mockitousage/bugs/deepstubs/DeepStubsWronglyReportsSerializationProblemsTest.java
new file mode 100644
index 0000000..8c20f80
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/deepstubs/DeepStubsWronglyReportsSerializationProblemsTest.java
@@ -0,0 +1,32 @@
+package org.mockitousage.bugs.deepstubs;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+/**
+ * In GH issue 99 : https://github.com/mockito/mockito/issues/99
+ */
+public class DeepStubsWronglyReportsSerializationProblemsTest {
+
+    @Test
+    public void should_not_raise_a_mockito_exception_about_serialization_when_accessing_deep_stub() {
+        NotSerializableShouldBeMocked the_deep_stub = mock(ToBeDeepStubbed.class, RETURNS_DEEP_STUBS).getSomething();
+        assertThat(the_deep_stub).isNotNull();
+    }
+
+    public static class ToBeDeepStubbed {
+        public ToBeDeepStubbed() { }
+
+        public NotSerializableShouldBeMocked getSomething() {
+            return null;
+        }
+    }
+
+    public static class NotSerializableShouldBeMocked {
+        NotSerializableShouldBeMocked(String mandatory_param) { }
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/injection/ChildWithSameParentFieldInjectionTest.java b/src/test/java/org/mockitousage/bugs/injection/ChildWithSameParentFieldInjectionTest.java
new file mode 100644
index 0000000..c7f02c3
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/injection/ChildWithSameParentFieldInjectionTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs.injection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertNotNull;
+
+// issue 289
+@RunWith(MockitoJUnitRunner.class)
+public class ChildWithSameParentFieldInjectionTest {
+    @InjectMocks
+    private System system;
+
+    @Mock
+    private SomeService someService;
+
+    @Test
+    public void parent_field_is_not_null() {
+        assertNotNull(((AbstractSystem) system).someService);
+    }
+
+    @Test
+    public void child_field_is_not_null() {
+        assertNotNull(system.someService);
+    }
+
+    public static class System extends AbstractSystem {
+        private SomeService someService;
+
+        public void doSomethingElse() {
+            someService.doSomething();
+        }
+    }
+
+    public static class AbstractSystem {
+        private SomeService someService;
+
+        public void doSomething() {
+            someService.doSomething();
+        }
+    }
+
+    public static class SomeService {
+        public void doSomething() {
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/injection/InjectMocksShouldTryPropertySettersFirstBeforeFieldAccessTest.java b/src/test/java/org/mockitousage/bugs/injection/InjectMocksShouldTryPropertySettersFirstBeforeFieldAccessTest.java
new file mode 100644
index 0000000..10070c6
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/injection/InjectMocksShouldTryPropertySettersFirstBeforeFieldAccessTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs.injection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Issue 211 : @InjectMocks should carry out their work by the method (and not by field) if available
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class InjectMocksShouldTryPropertySettersFirstBeforeFieldAccessTest {
+    @Mock List<?> fieldAccess;
+    @Mock List<?> propertySetterAccess;
+    @InjectMocks BeanAwaitingInjection awaitingInjection;
+
+    @Test
+    public void shouldInjectUsingPropertySetterIfAvailable() {
+        assertTrue(awaitingInjection.propertySetterUsed);
+    }
+
+    @Test
+    public void shouldInjectFieldIfNoSetter() {
+        assertEquals(fieldAccess, awaitingInjection.fieldAccess);
+    }
+
+    static class BeanAwaitingInjection {
+        List<?> fieldAccess;
+        List<?> propertySetterAccess;
+        boolean propertySetterUsed;
+
+        public void setPropertySetterAccess(List<?> propertySetterAccess) {
+            // don't care if field is set, the setter can do whatever it want.
+            propertySetterUsed = true;
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/injection/InjectionByTypeShouldFirstLookForExactTypeThenAncestorTest.java b/src/test/java/org/mockitousage/bugs/injection/InjectionByTypeShouldFirstLookForExactTypeThenAncestorTest.java
new file mode 100644
index 0000000..e4957d3
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/injection/InjectionByTypeShouldFirstLookForExactTypeThenAncestorTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs.injection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.lang.reflect.Field;
+
+import static org.junit.Assert.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class InjectionByTypeShouldFirstLookForExactTypeThenAncestorTest {
+
+    private static final Object REFERENCE = new Object();
+
+    @Mock private Bean mockedBean;
+
+    @InjectMocks private Service illegalInjectionExample = new Service();
+    @InjectMocks private ServiceWithReversedOrder reversedOrderService = new ServiceWithReversedOrder();
+    @InjectMocks private WithNullObjectField withNullObjectField = new WithNullObjectField();
+
+    @Test
+    public void just_for_information_fields_are_read_in_declaration_order_see_Service() {
+        Field[] declaredFields = Service.class.getDeclaredFields();
+
+        assertEquals("mockShouldNotGoInHere", declaredFields[0].getName());
+        assertEquals("mockShouldGoInHere", declaredFields[1].getName());
+    }
+
+    @Test
+    public void mock_should_be_injected_once_and_in_the_best_matching_type() {
+        assertSame(REFERENCE, illegalInjectionExample.mockShouldNotGoInHere);
+        assertSame(mockedBean, illegalInjectionExample.mockShouldGoInHere);
+    }
+
+    @Test
+    public void should_match_be_consistent_regardless_of_order() {
+        assertSame(REFERENCE, reversedOrderService.mockShouldNotGoInHere);
+        assertSame(mockedBean, reversedOrderService.mockShouldGoInHere);
+    }
+
+    @Test
+    public void should_inject_the_mock_only_once_and_in_the_correct_type() {
+        assertNull(withNullObjectField.keepMeNull);
+        assertSame(mockedBean, withNullObjectField.injectMePlease);
+    }
+
+    public static class Bean {}
+
+    public static class Service {
+        public final Object mockShouldNotGoInHere = REFERENCE;
+        public Bean mockShouldGoInHere;
+    }
+
+    public static class ServiceWithReversedOrder {
+        public Bean mockShouldGoInHere;
+        public final Object mockShouldNotGoInHere = REFERENCE;
+    }
+
+    class WithNullObjectField{
+        Bean injectMePlease;
+        Object keepMeNull = null;
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/injection/Issue353InjectionMightNotHappenInCertainConfigurationTest.java b/src/test/java/org/mockitousage/bugs/injection/Issue353InjectionMightNotHappenInCertainConfigurationTest.java
new file mode 100644
index 0000000..d223626
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/injection/Issue353InjectionMightNotHappenInCertainConfigurationTest.java
@@ -0,0 +1,35 @@
+package org.mockitousage.bugs.injection;
+
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertSame;
+
+@RunWith(MockitoJUnitRunner.class)
+public class Issue353InjectionMightNotHappenInCertainConfigurationTest {
+    @Mock Map<String, String> stringString_that_matches_field;
+    @Mock Map<String, Integer> mockStringInteger_was_not_injected;
+    @InjectMocks FooService fooService;
+
+    @Test
+    public void when_identical_types_and_the_correct_mock_name_is_greater_than_the_non_matching_name_then_injection_occurs_only_on_the_named_one() {
+        assertThat("stringString_that_matches_field".compareTo("mockStringInteger_was_not_injected")).isGreaterThanOrEqualTo(1);
+
+        assertSame(stringString_that_matches_field, fooService.stringString_that_matches_field);
+        assertSame(mockStringInteger_was_not_injected, fooService.stringInteger_field);
+    }
+
+    public static class FooService {
+        Map<String, Integer> stringInteger_field = new HashMap<String, Integer>();
+        Map<String, String> stringString_that_matches_field = new HashMap<String, String>();
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/injection/ParentTestMockInjectionTest.java b/src/test/java/org/mockitousage/bugs/injection/ParentTestMockInjectionTest.java
new file mode 100644
index 0000000..660883f
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/injection/ParentTestMockInjectionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs.injection;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.junit.Assert.assertNotNull;
+
+// issue 229 : @Mock fields in super test class are not injected on @InjectMocks fields
+public class ParentTestMockInjectionTest {
+
+    @Test
+    public void injectMocksShouldInjectMocksFromTestSuperClasses() {
+        ImplicitTest it = new ImplicitTest();
+        MockitoAnnotations.initMocks(it);
+
+        assertNotNull(it.daoFromParent);
+        assertNotNull(it.daoFromSub);
+        assertNotNull(it.sut.daoFromParent);
+        assertNotNull(it.sut.daoFromSub);
+    }
+
+    @Ignore
+    public static abstract class BaseTest {
+        @Mock protected DaoA daoFromParent;
+    }
+
+    @Ignore("JUnit test under test : don't test this!")
+    public static class ImplicitTest extends BaseTest {
+        @InjectMocks private TestedSystem sut = new TestedSystem();
+
+        @Mock private DaoB daoFromSub;
+
+        @Before
+        public void setup() {
+            MockitoAnnotations.initMocks(this);
+        }
+
+        @Test
+        public void noNullPointerException() {
+            sut.businessMethod();
+        }
+    }
+
+    public static class TestedSystem {
+        private DaoA daoFromParent;
+        private DaoB daoFromSub;
+
+        public void businessMethod() {
+            daoFromParent.doQuery();
+            daoFromSub.doQuery();
+        }
+    }
+
+
+    public static class DaoA {
+        public void doQuery() { }
+    }
+
+    public static class DaoB {
+        public void doQuery() { }
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/injection/ShouldNotTryToInjectInFinalOrStaticFieldsTest.java b/src/test/java/org/mockitousage/bugs/injection/ShouldNotTryToInjectInFinalOrStaticFieldsTest.java
new file mode 100644
index 0000000..bbe5233
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/injection/ShouldNotTryToInjectInFinalOrStaticFieldsTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs.injection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.*;
+
+import static org.junit.Assert.assertNotSame;
+
+// issue 262
+@RunWith(MockitoJUnitRunner.class)
+public class ShouldNotTryToInjectInFinalOrStaticFieldsTest {
+
+    public static class ExampleService {
+        public static final List<String> CONSTANTS = Arrays.asList("c1", "c1");
+        public final Set<String> aSet = new HashSet<String>();
+    }
+
+    @Spy private List<String> unrelatedList = new ArrayList<String>();
+    @Mock private Set<String> unrelatedSet;
+
+    @InjectMocks private ExampleService exampleService = new ExampleService();
+
+    @Test
+    public void dont_fail_with_CONSTANTS() throws Exception {
+    }
+
+    @Test
+    public void dont_inject_in_final() {
+        assertNotSame(unrelatedSet, exampleService.aSet);
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/bugs/varargs/VarargsAndAnyObjectPicksUpExtraInvocationsTest.java b/src/test/java/org/mockitousage/bugs/varargs/VarargsAndAnyObjectPicksUpExtraInvocationsTest.java
new file mode 100644
index 0000000..7bf4271
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/varargs/VarargsAndAnyObjectPicksUpExtraInvocationsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs.varargs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class VarargsAndAnyObjectPicksUpExtraInvocationsTest extends TestBase {
+    public interface TableBuilder {
+        void newRow(String trAttributes, String... cells);
+    }
+
+    @Mock
+    TableBuilder table;
+
+    @Test
+    public void shouldVerifyCorrectlyWithAnyVarargs() {
+        //when
+        table.newRow("qux", "foo", "bar", "baz");
+        table.newRow("abc", "def");
+
+        //then
+        verify(table, times(2)).newRow(anyString(), (String[]) anyVararg());
+    }
+
+    @Test
+    public void shouldVerifyCorrectlyNumberOfInvocationsUsingAnyVarargAndEqualArgument() {
+        //when
+        table.newRow("x", "foo", "bar", "baz");
+        table.newRow("x", "def");
+
+        //then
+        verify(table, times(2)).newRow(eq("x"), (String[]) anyVararg());
+    }
+
+    @Test
+    public void shouldVerifyCorrectlyNumberOfInvocationsWithVarargs() {
+        //when
+        table.newRow("qux", "foo", "bar", "baz");
+        table.newRow("abc", "def");
+
+        //then
+        verify(table).newRow(anyString(), eq("foo"), anyString(), anyString());
+        verify(table).newRow(anyString(), anyString());
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/varargs/VarargsErrorWhenCallingRealMethodTest.java b/src/test/java/org/mockitousage/bugs/varargs/VarargsErrorWhenCallingRealMethodTest.java
new file mode 100644
index 0000000..cc0ab21
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/varargs/VarargsErrorWhenCallingRealMethodTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs.varargs;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+public class VarargsErrorWhenCallingRealMethodTest extends TestBase {
+
+    class Foo {
+        int blah(String a, String b, Object ... c) {
+            return 1;
+        }
+    }
+
+    @Test
+    public void shouldNotThrowAnyException() throws Exception {
+        Foo foo = mock(Foo.class);
+
+        when(foo.blah(anyString(), anyString())).thenCallRealMethod();
+
+        assertEquals(1, foo.blah("foo", "bar"));
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/varargs/VarargsNotPlayingWithAnyObjectTest.java b/src/test/java/org/mockitousage/bugs/varargs/VarargsNotPlayingWithAnyObjectTest.java
new file mode 100644
index 0000000..f2a1511
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/varargs/VarargsNotPlayingWithAnyObjectTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.bugs.varargs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+//see issue 62
+public class VarargsNotPlayingWithAnyObjectTest extends TestBase {
+
+    interface VarargMethod {
+        Object run(String... args);
+    }
+
+    @Mock VarargMethod mock;
+
+    @Test
+    public void shouldMatchAnyVararg() {
+        mock.run("a", "b");
+
+        verify(mock).run(anyString(), anyString());
+        verify(mock).run((String) anyObject(), (String) anyObject());
+
+        verify(mock).run((String[]) anyVararg());
+
+        verify(mock, never()).run();
+        verify(mock, never()).run(anyString(), eq("f"));
+    }
+
+    //we cannot use anyObject() for entire varargs because it makes the verification pick up extra invocations
+    //see other tests in this package
+    @Test
+    public void shouldNotAllowUsingAnyObjectForVarArgs() {
+        mock.run("a", "b");
+
+        try {
+            verify(mock).run((String[]) anyObject());
+            fail();
+        } catch (AssertionError e) {}
+    }
+
+    @Test
+    public void shouldStubUsingAnyVarargs() {
+        when(mock.run((String[]) anyVararg())).thenReturn("foo");
+
+        assertEquals("foo", mock.run("a", "b"));
+    }
+}
diff --git a/src/test/java/org/mockitousage/configuration/ClassCacheVersusClassReloadingTest.java b/src/test/java/org/mockitousage/configuration/ClassCacheVersusClassReloadingTest.java
new file mode 100644
index 0000000..edc0a8b
--- /dev/null
+++ b/src/test/java/org/mockitousage/configuration/ClassCacheVersusClassReloadingTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.configuration;
+
+
+import org.junit.Test;
+import org.mockito.internal.configuration.ConfigurationAccess;
+import org.mockitoutil.SimplePerRealmReloadingClassLoader;
+
+import java.util.concurrent.Callable;
+
+import static org.mockito.Mockito.mock;
+
+public class ClassCacheVersusClassReloadingTest {
+    // TODO refactor to use ClassLoaders
+
+    private SimplePerRealmReloadingClassLoader testMethodClassLoaderRealm = new SimplePerRealmReloadingClassLoader(reloadMockito());
+
+    @Test
+    public void should_not_throw_ClassCastException_when_objenesis_cache_disabled() throws Exception {
+        prepareMockitoAndDisableObjenesisCache();
+
+        doInNewChildRealm(testMethodClassLoaderRealm, "org.mockitousage.configuration.ClassCacheVersusClassReloadingTest$DoTheMocking");
+        doInNewChildRealm(testMethodClassLoaderRealm, "org.mockitousage.configuration.ClassCacheVersusClassReloadingTest$DoTheMocking");
+    }
+
+    public static class DoTheMocking implements Callable<Object> {
+        public Object call() throws Exception {
+            Class<?> clazz = this.getClass().getClassLoader().loadClass("org.mockitousage.configuration.ClassToBeMocked");
+            return mock(clazz);
+        }
+    }
+
+    private static void doInNewChildRealm(ClassLoader parentRealm, String callableCalledInClassLoaderRealm) throws Exception {
+        new SimplePerRealmReloadingClassLoader(parentRealm, reloadScope()).doInRealm(callableCalledInClassLoaderRealm);
+    }
+
+    private static SimplePerRealmReloadingClassLoader.ReloadClassPredicate reloadScope() {
+        return new SimplePerRealmReloadingClassLoader.ReloadClassPredicate() {
+            public boolean acceptReloadOf(String qualifiedName) {
+                return "org.mockitousage.configuration.ClassCacheVersusClassReloadingTest$DoTheMocking".equals(qualifiedName)
+                    || "org.mockitousage.configuration.ClassToBeMocked".equals(qualifiedName);
+            }
+        };
+    }
+
+    private void prepareMockitoAndDisableObjenesisCache() throws Exception {
+        testMethodClassLoaderRealm.doInRealm("org.mockitousage.configuration.ClassCacheVersusClassReloadingTest$PrepareMockito");
+    }
+
+    public static class PrepareMockito implements Callable<Boolean> {
+        public Boolean call() throws Exception {
+            Class.forName("org.mockito.Mockito");
+            ConfigurationAccess.getConfig().overrideEnableClassCache(false);
+            return Boolean.TRUE;
+        }
+    }
+
+    private static SimplePerRealmReloadingClassLoader.ReloadClassPredicate reloadMockito() {
+        return new SimplePerRealmReloadingClassLoader.ReloadClassPredicate() {
+            public boolean acceptReloadOf(String qualifiedName) {
+                return (!qualifiedName.contains("net.bytebuddy") && qualifiedName.contains("org.mockito"));
+            }
+        };
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/configuration/ClassToBeMocked.java b/src/test/java/org/mockitousage/configuration/ClassToBeMocked.java
new file mode 100644
index 0000000..adc863d
--- /dev/null
+++ b/src/test/java/org/mockitousage/configuration/ClassToBeMocked.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.configuration;
+
+/**
+ * Some class to mock that is created via Class.forClass
+ */
+public class ClassToBeMocked { }
diff --git a/src/test/java/org/mockitousage/configuration/CustomizedAnnotationForSmartMockTest.java b/src/test/java/org/mockitousage/configuration/CustomizedAnnotationForSmartMockTest.java
new file mode 100644
index 0000000..c82f12d
--- /dev/null
+++ b/src/test/java/org/mockitousage/configuration/CustomizedAnnotationForSmartMockTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.configuration;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Set;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.configuration.MockitoConfiguration;
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.verify;
+
+
+/**
+ * @see MockitoConfiguration#getAnnotationEngine() for the custom smartmock injection engine
+ */
+public class CustomizedAnnotationForSmartMockTest extends TestBase {
+
+    @SmartMock IMethods smartMock;
+
+    @Test
+    public void shouldUseCustomAnnotation() {
+        assertEquals("SmartMock should return empty String by default", "", smartMock.simpleMethod(1));
+        verify(smartMock).simpleMethod(1);
+    }
+
+    @Target({FIELD })
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface SmartMock {}
+
+    public static class CustomInjectingAnnotationEngine extends InjectingAnnotationEngine {
+        @Override
+        protected void onInjection(Object testClassInstance, Class<?> clazz, Set<Field> mockDependentFields, Set<Object> mocks) {
+            for (Field field : clazz.getDeclaredFields()) {
+                if (field.isAnnotationPresent(SmartMock.class)) {
+                    field.setAccessible(true);
+                    try {
+                        field.set(Modifier.isStatic(field.getModifiers()) ? null : testClassInstance, Mockito.mock(field.getType(), Mockito.RETURNS_SMART_NULLS));
+                    } catch (Exception exception) {
+                        throw new AssertionError(exception.getMessage());
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/constructor/CreatingMocksWithConstructorTest.java b/src/test/java/org/mockitousage/constructor/CreatingMocksWithConstructorTest.java
new file mode 100644
index 0000000..2295593
--- /dev/null
+++ b/src/test/java/org/mockitousage/constructor/CreatingMocksWithConstructorTest.java
@@ -0,0 +1,165 @@
+package org.mockitousage.constructor;
+
+import java.util.List;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.mock.SerializableMode;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
+
+public class CreatingMocksWithConstructorTest extends TestBase {
+
+    static abstract class AbstractMessage {
+        private final String message;
+        AbstractMessage() {
+            this.message = "hey!";
+        }
+        String getMessage() {
+            return message;
+        }
+    }
+
+    static class Message extends AbstractMessage {}
+    class InnerClass extends AbstractMessage {}
+
+    @Test
+    public void can_create_mock_with_constructor() {
+        Message mock = mock(Message.class, withSettings().useConstructor().defaultAnswer(CALLS_REAL_METHODS));
+        //the message is a part of state of the mocked type that gets initialized in constructor
+        assertEquals("hey!", mock.getMessage());
+    }
+
+    @Test
+    public void can_mock_abstract_classes() {
+        AbstractMessage mock = mock(AbstractMessage.class, withSettings().useConstructor().defaultAnswer(CALLS_REAL_METHODS));
+        assertEquals("hey!", mock.getMessage());
+    }
+
+    @Test
+    public void can_spy_abstract_classes() {
+        AbstractMessage mock = spy(AbstractMessage.class);
+        assertEquals("hey!", mock.getMessage());
+    }
+
+    @Test
+    public void can_mock_inner_classes() {
+        InnerClass mock = mock(InnerClass.class, withSettings().useConstructor().outerInstance(this).defaultAnswer(CALLS_REAL_METHODS));
+        assertEquals("hey!", mock.getMessage());
+    }
+
+    static class HasConstructor {
+        HasConstructor(String x) {}
+    }
+
+    @Test
+    public void exception_message_when_constructor_not_found() {
+        try {
+            //when
+            spy(HasConstructor.class);
+            //then
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessage("Unable to create mock instance of type 'HasConstructor'");
+            assertThat(e.getCause()).hasMessageContaining("0-arg constructor");
+        }
+    }
+
+    @Test
+    public void mocking_inner_classes_with_wrong_outer_instance() {
+        try {
+            //when
+            mock(InnerClass.class, withSettings().useConstructor().outerInstance("foo").defaultAnswer(CALLS_REAL_METHODS));
+            //then
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessage("Unable to create mock instance of type 'InnerClass'");
+            assertThat(e.getCause()).hasMessageContaining("Unable to find a matching 1-arg constructor for the outer instance.");
+        }
+    }
+
+    @Test
+    public void mocking_interfaces_with_constructor() {
+        //at the moment this is allowed however we can be more strict if needed
+        //there is not much sense in creating a spy of an interface
+        mock(IMethods.class, withSettings().useConstructor());
+        spy(IMethods.class);
+    }
+
+    @Test
+    public void prevents_across_jvm_serialization_with_constructor() {
+        try {
+            //when
+            mock(AbstractMessage.class, withSettings().useConstructor().serializable(SerializableMode.ACROSS_CLASSLOADERS));
+            //then
+            fail();
+        } catch (MockitoException e) {
+            assertEquals("Mocks instantiated with constructor cannot be combined with " + SerializableMode.ACROSS_CLASSLOADERS + " serialization mode.", e.getMessage());
+        }
+    }
+
+    static abstract class AbstractThing {
+        abstract String name();
+        String fullName() {
+            return "abstract " + name();
+        }
+    }
+
+    @Test
+    public void abstract_method_returns_default() {
+        AbstractThing thing = spy(AbstractThing.class);
+        assertEquals("abstract null", thing.fullName());
+    }
+
+    @Test
+    public void abstract_method_stubbed() {
+        AbstractThing thing = spy(AbstractThing.class);
+        when(thing.name()).thenReturn("me");
+        assertEquals("abstract me", thing.fullName());
+    }
+
+    @Test
+    public void interface_method_stubbed() {
+        List<?> list = spy(List.class);
+        when(list.size()).thenReturn(12);
+        assertEquals(12, list.size());
+    }
+
+    @Test
+    public void calls_real_interface_method() {
+        List list = mock(List.class, withSettings().defaultAnswer(CALLS_REAL_METHODS));
+        assertNull(list.get(1));
+    }
+
+    @Test
+    public void handles_bridge_methods_correctly() {
+        SomeConcreteClass<Integer> testBug = spy(new SomeConcreteClass<Integer>());
+        assertEquals("value", testBug.getValue(0));
+    }
+
+    public abstract class SomeAbstractClass<T> {
+
+        protected abstract String getRealValue(T value);
+
+        public String getValue(T value) {
+            return getRealValue(value);
+        }
+    }
+
+    public class SomeConcreteClass<T extends Number> extends SomeAbstractClass<T> {
+
+        @Override
+        protected String getRealValue(T value) {
+            return "value";
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/customization/BDDMockitoTest.java b/src/test/java/org/mockitousage/customization/BDDMockitoTest.java
new file mode 100644
index 0000000..6830765
--- /dev/null
+++ b/src/test/java/org/mockitousage/customization/BDDMockitoTest.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.customization;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitousage.IMethods;
+import org.mockitousage.MethodsImpl;
+import org.mockitoutil.TestBase;
+
+import java.util.Set;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.BDDMockito.*;
+
+public class BDDMockitoTest extends TestBase {
+
+    @Mock
+    IMethods mock;
+
+    @Test
+    public void should_stub() throws Exception {
+        given(mock.simpleMethod("foo")).willReturn("bar");
+
+        Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("bar");
+        Assertions.assertThat(mock.simpleMethod("whatever")).isEqualTo(null);
+    }
+
+    @Test
+    public void should_stub_with_throwable() throws Exception {
+        given(mock.simpleMethod("foo")).willThrow(new SomethingWasWrong());
+
+        try {
+            Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    public void should_stub_with_throwable_class() throws Exception {
+        given(mock.simpleMethod("foo")).willThrow(SomethingWasWrong.class);
+
+        try {
+            Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void should_stub_with_throwable_classes() throws Exception {
+        // unavoidable 'unchecked generic array creation' warning (from JDK7 onward)
+        given(mock.simpleMethod("foo")).willThrow(SomethingWasWrong.class, AnotherThingWasWrong.class);
+
+        try {
+            Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    public void should_stub_with_answer() throws Exception {
+        given(mock.simpleMethod(anyString())).willAnswer(new Answer<String>() {
+            public String answer(InvocationOnMock invocation) throws Throwable {
+                return invocation.getArgument(0);
+            }
+        });
+
+        Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+    }
+
+    @Test
+    public void should_stub_with_will_answer_alias() throws Exception {
+        given(mock.simpleMethod(anyString())).will(new Answer<String>() {
+            public String answer(InvocationOnMock invocation) throws Throwable {
+                return invocation.getArgument(0);
+            }
+        });
+
+        Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+    }
+
+    @Test
+    public void should_stub_consecutively() throws Exception {
+        given(mock.simpleMethod(anyString()))
+                .willReturn("foo")
+                .willReturn("bar");
+
+        Assertions.assertThat(mock.simpleMethod("whatever")).isEqualTo("foo");
+        Assertions.assertThat(mock.simpleMethod("whatever")).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_return_consecutively() throws Exception {
+        given(mock.objectReturningMethodNoArgs())
+                .willReturn("foo", "bar", 12L, new byte[0]);
+
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo("foo");
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo("bar");
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo(12L);
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo(new byte[0]);
+    }
+
+    @Test
+    public void should_stub_consecutively_with_call_real_method() throws Exception {
+        MethodsImpl mock = mock(MethodsImpl.class);
+        willReturn("foo").willCallRealMethod()
+                .given(mock).simpleMethod();
+
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("foo");
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo(null);
+    }
+
+    @Test
+    public void should_stub_void() throws Exception {
+        willThrow(new SomethingWasWrong()).given(mock).voidMethod();
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    public void should_stub_void_with_exception_class() throws Exception {
+        willThrow(SomethingWasWrong.class).given(mock).voidMethod();
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void should_stub_void_with_exception_classes() throws Exception {
+        willThrow(SomethingWasWrong.class, AnotherThingWasWrong.class).given(mock).voidMethod();
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    public void should_stub_void_consecutively() throws Exception {
+        willDoNothing()
+                .willThrow(new SomethingWasWrong())
+                .given(mock).voidMethod();
+
+        mock.voidMethod();
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    public void should_stub_void_consecutively_with_exception_class() throws Exception {
+        willDoNothing()
+                .willThrow(SomethingWasWrong.class)
+                .given(mock).voidMethod();
+
+        mock.voidMethod();
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (SomethingWasWrong expected) {
+        }
+    }
+
+    @Test
+    public void should_stub_using_do_return_style() throws Exception {
+        willReturn("foo").given(mock).simpleMethod("bar");
+
+        Assertions.assertThat(mock.simpleMethod("boooo")).isEqualTo(null);
+        Assertions.assertThat(mock.simpleMethod("bar")).isEqualTo("foo");
+    }
+
+    @Test
+    public void should_stub_using_do_answer_style() throws Exception {
+        willAnswer(new Answer<String>() {
+            public String answer(InvocationOnMock invocation) throws Throwable {
+                return invocation.getArgument(0);
+            }
+        })
+                .given(mock).simpleMethod(anyString());
+
+        Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+    }
+
+    @Test
+    public void should_stub_by_delegating_to_real_method() throws Exception {
+        //given
+        Dog dog = mock(Dog.class);
+        //when
+        willCallRealMethod().given(dog).bark();
+        //then
+        Assertions.assertThat(dog.bark()).isEqualTo("woof");
+    }
+
+    @Test
+    public void should_stub_by_delegating_to_real_method_using_typical_stubbing_syntax() throws Exception {
+        //given
+        Dog dog = mock(Dog.class);
+        //when
+        given(dog.bark()).willCallRealMethod();
+        //then
+        Assertions.assertThat(dog.bark()).isEqualTo("woof");
+    }
+
+    @Test
+    public void should_all_stubbed_mock_reference_access() throws Exception {
+        Set<?> expectedMock = mock(Set.class);
+
+        Set<?> returnedMock = given(expectedMock.isEmpty()).willReturn(false).getMock();
+
+        Assertions.assertThat(returnedMock).isEqualTo(expectedMock);
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void should_validate_mock_when_verifying() {
+        then("notMock").should();
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void should_validate_mock_when_verifying_with_expected_number_of_invocations() {
+        then("notMock").should(times(19));
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void should_validate_mock_when_verifying_no_more_interactions() {
+        then("notMock").should();
+    }
+
+    @Test(expected = WantedButNotInvoked.class)
+    public void should_fail_for_expected_behavior_that_did_not_happen() {
+        then(mock).should().booleanObjectReturningMethod();
+    }
+
+    @Test
+    public void should_pass_for_expected_behavior_that_happened() {
+        mock.booleanObjectReturningMethod();
+
+        then(mock).should().booleanObjectReturningMethod();
+        then(mock).shouldHaveNoMoreInteractions();
+    }
+
+    @Test
+    public void should_validate_that_mock_did_not_have_any_interactions() {
+        then(mock).shouldHaveZeroInteractions();
+    }
+
+    @Test
+    public void should_fail_when_mock_had_unwanted_interactions() {
+        mock.booleanObjectReturningMethod();
+
+        try {
+            then(mock).shouldHaveZeroInteractions();
+            fail("should have reported this interaction wasn't wanted");
+        } catch (NoInteractionsWanted expected) {
+        }
+    }
+
+    @Test
+    public void should_fail_when_mock_had_more_interactions_than_expected() {
+        mock.booleanObjectReturningMethod();
+        mock.byteObjectReturningMethod();
+
+        then(mock).should().booleanObjectReturningMethod();
+        try {
+            then(mock).shouldHaveNoMoreInteractions();
+            fail("should have reported that no more interactions were wanted");
+        } catch (NoInteractionsWanted expected) {
+        }
+    }
+
+    @Test
+    public void should_pass_for_interactions_that_happened_in_correct_order() {
+        mock.booleanObjectReturningMethod();
+        mock.arrayReturningMethod();
+
+        InOrder inOrder = inOrder(mock);
+        then(mock).should(inOrder).booleanObjectReturningMethod();
+        then(mock).should(inOrder).arrayReturningMethod();
+    }
+
+    @Test
+    public void should_fail_for_interactions_that_were_in_wrong_order() {
+        InOrder inOrder = inOrder(mock);
+
+        mock.arrayReturningMethod();
+        mock.booleanObjectReturningMethod();
+
+        then(mock).should(inOrder).booleanObjectReturningMethod();
+        try {
+            then(mock).should(inOrder).arrayReturningMethod();
+            fail("should have raise in order verification failure on second verify call");
+        } catch (VerificationInOrderFailure expected) {
+        }
+    }
+
+    @Test(expected = WantedButNotInvoked.class)
+    public void should_fail_when_checking_order_of_interactions_that_did_not_happen() {
+        then(mock).should(inOrder(mock)).booleanObjectReturningMethod();
+    }
+
+    @Test
+    public void should_pass_fluent_bdd_scenario() {
+        Bike bike = new Bike();
+        Person person = mock(Person.class);
+        Police police = mock(Police.class);
+
+        person.ride(bike);
+        person.ride(bike);
+
+        then(person).should(times(2)).ride(bike);
+        then(police).shouldHaveZeroInteractions();
+    }
+
+    @Test
+    public void should_pass_fluent_bdd_scenario_with_ordered_verification() {
+        Bike bike = new Bike();
+        Car car = new Car();
+        Person person = mock(Person.class);
+
+        person.drive(car);
+        person.ride(bike);
+        person.ride(bike);
+
+        InOrder inOrder = inOrder(person);
+        then(person).should(inOrder).drive(car);
+        then(person).should(inOrder, times(2)).ride(bike);
+    }
+
+    @Test
+    public void should_pass_fluent_bdd_scenario_with_ordered_verification_for_two_mocks() {
+        Car car = new Car();
+        Person person = mock(Person.class);
+        Police police = mock(Police.class);
+
+        person.drive(car);
+        person.drive(car);
+        police.chase(car);
+
+        InOrder inOrder = inOrder(person, police);
+        then(person).should(inOrder, times(2)).drive(car);
+        then(police).should(inOrder).chase(car);
+    }
+
+    static class Person {
+
+        void ride(Bike bike) {
+        }
+
+        void drive(Car car) {
+        }
+    }
+
+    static class Bike {
+
+    }
+
+    static class Car {
+
+    }
+
+    static class Police {
+
+        void chase(Car car) {
+        }
+    }
+
+    class Dog {
+
+        public String bark() {
+            return "woof";
+        }
+    }
+
+    private class SomethingWasWrong extends RuntimeException {
+
+    }
+
+    private class AnotherThingWasWrong extends RuntimeException {
+
+    }
+}
diff --git a/src/test/java/org/mockitousage/debugging/Foo.java b/src/test/java/org/mockitousage/debugging/Foo.java
new file mode 100644
index 0000000..be52a98
--- /dev/null
+++ b/src/test/java/org/mockitousage/debugging/Foo.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.debugging;
+
+interface Foo {
+    String giveMeSomeString(String param);
+    void doSomething(String param);
+}
diff --git a/src/test/java/org/mockitousage/debugging/InvocationListenerCallbackTest.java b/src/test/java/org/mockitousage/debugging/InvocationListenerCallbackTest.java
new file mode 100644
index 0000000..1e1273f
--- /dev/null
+++ b/src/test/java/org/mockitousage/debugging/InvocationListenerCallbackTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.debugging;
+
+import org.assertj.core.api.Condition;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.listeners.MethodInvocationReport;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.willReturn;
+import static org.mockito.Mockito.*;
+
+
+/**
+ * Ensures that custom listeners can be registered and will be called every time
+ * a method on a mock is invoked.
+ */
+public class InvocationListenerCallbackTest {
+
+    @Test
+    public void should_call_single_listener_when_mock_return_normally() throws Exception {
+        // given
+        RememberingListener listener = new RememberingListener();
+        Foo foo = mock(Foo.class, withSettings().invocationListeners(listener));
+        willReturn("basil").given(foo).giveMeSomeString("herb");
+
+        // when
+        foo.giveMeSomeString("herb");
+
+        // then
+        assertThat(listener).is(notifiedFor("basil", getClass().getSimpleName()));
+    }
+
+    @Test
+    public void should_call_all_listener_when_mock_return_normally() throws Exception {
+        // given
+        RememberingListener listener1 = new RememberingListener();
+        RememberingListener listener2 = new RememberingListener();
+        Foo foo = mock(Foo.class, withSettings().invocationListeners(listener1, listener2));
+        given(foo.giveMeSomeString("herb")).willReturn("rosemary");
+
+        // when
+        foo.giveMeSomeString("herb");
+
+        // then
+        assertThat(listener1).is(notifiedFor("rosemary", getClass().getSimpleName()));
+        assertThat(listener2).is(notifiedFor("rosemary", getClass().getSimpleName()));
+    }
+
+    @Test
+    public void should_call_all_listener_when_mock_throws_exception() throws Exception {
+        // given
+        InvocationListener listener1 = mock(InvocationListener.class, "listener1");
+        InvocationListener listener2 = mock(InvocationListener.class, "listener2");
+        Foo foo = mock(Foo.class, withSettings().invocationListeners(listener1, listener2));
+        doThrow(new OvenNotWorking()).when(foo).doSomething("cook");
+
+        // when
+        try {
+            foo.doSomething("cook");
+            fail("Exception expected.");
+        } catch (OvenNotWorking actualException) {
+            // then
+            InOrder orderedVerify = inOrder(listener1, listener2);
+            orderedVerify.verify(listener1).reportInvocation(any(MethodInvocationReport.class));
+            orderedVerify.verify(listener2).reportInvocation(any(MethodInvocationReport.class));
+        }
+    }
+
+    private static Condition<RememberingListener> notifiedFor(final Object returned, final String location) {
+        return new Condition<RememberingListener>() {
+            public boolean matches(RememberingListener toBeAsserted) {
+                assertThat(toBeAsserted.returnValue).isEqualTo(returned);
+                assertThat(toBeAsserted.invocation).isNotNull();
+                assertThat(toBeAsserted.locationOfStubbing).contains(location);
+                return true;
+            }
+        };
+    }
+
+    private static class RememberingListener implements InvocationListener {
+        DescribedInvocation invocation;
+        Object returnValue;
+        String locationOfStubbing;
+
+        public void reportInvocation(MethodInvocationReport mcr) {
+            this.invocation = mcr.getInvocation();
+            this.returnValue = mcr.getReturnedValue();
+            this.locationOfStubbing = mcr.getLocationOfStubbing();
+        }
+    }
+
+    private static class OvenNotWorking extends RuntimeException { }
+}
diff --git a/src/test/java/org/mockitousage/debugging/InvocationsPrinterTest.java b/src/test/java/org/mockitousage/debugging/InvocationsPrinterTest.java
new file mode 100644
index 0000000..b3343d4
--- /dev/null
+++ b/src/test/java/org/mockitousage/debugging/InvocationsPrinterTest.java
@@ -0,0 +1,81 @@
+package org.mockitousage.debugging;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.internal.debugging.InvocationsPrinter;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+public class InvocationsPrinterTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @Test public void no_invocations() {
+        assertThat(new InvocationsPrinter().printInvocations(mock)).isEqualTo("No interactions and stubbings found for mock: mock");
+    }
+
+    @Test public void prints_invocations() {
+        mock.simpleMethod(100);
+        triggerInteraction();
+
+        assertThat(filterLineNo(new InvocationsPrinter().printInvocations(mock)))
+                .isEqualTo(filterLineNo("[Mockito] Interactions of: mock\n" +
+                        " 1. mock.simpleMethod(100);\n" +
+                        "  -> at org.mockitousage.debugging.InvocationsPrinterTest.prints_invocations(InvocationsPrinterTest.java:0)\n" +
+                        " 2. mock.otherMethod();\n" +
+                        "  -> at org.mockitousage.debugging.InvocationsPrinterTest.triggerInteraction(InvocationsPrinterTest.java:0)\n"));
+    }
+
+    @Test public void prints_stubbings() {
+        triggerStubbing();
+
+        assertThat(filterLineNo(new InvocationsPrinter().printInvocations(mock)))
+                .isEqualTo(filterLineNo("[Mockito] Unused stubbings of: mock\n" +
+                        " 1. mock.simpleMethod(\"a\");\n" +
+                        "  - stubbed -> at org.mockitousage.debugging.InvocationsPrinterTest.triggerStubbing(InvocationsPrinterTest.java:70)\n"));
+    }
+
+    @Test public void prints_invocations_and_stubbings() {
+        triggerStubbing();
+
+        mock.simpleMethod("a");
+        triggerInteraction();
+
+        assertThat(filterLineNo(new InvocationsPrinter().printInvocations(mock)))
+                .isEqualTo(filterLineNo("[Mockito] Interactions of: mock\n" +
+                        " 1. mock.simpleMethod(\"a\");\n" +
+                        "  -> at org.mockitousage.debugging.InvocationsPrinterTest.prints_invocations_and_stubbings(InvocationsPrinterTest.java:49)\n" +
+                        "   - stubbed -> at org.mockitousage.debugging.InvocationsPrinterTest.triggerStubbing(InvocationsPrinterTest.java:73)\n" +
+                        " 2. mock.otherMethod();\n" +
+                        "  -> at org.mockitousage.debugging.InvocationsPrinterTest.triggerInteraction(InvocationsPrinterTest.java:34)\n"));
+    }
+
+    @Test public void prints_invocations_and_unused_stubbings() {
+        triggerStubbing();
+
+        mock.simpleMethod("b");
+        triggerInteraction();
+
+        assertThat(filterLineNo(new InvocationsPrinter().printInvocations(mock)))
+                .isEqualTo(filterLineNo("[Mockito] Interactions of: mock\n" +
+                        " 1. mock.simpleMethod(\"b\");\n" +
+                        "  -> at org.mockitousage.debugging.InvocationsPrinterTest.prints_invocations_and_unused_stubbings(InvocationsPrinterTest.java:55)\n" +
+                        " 2. mock.otherMethod();\n" +
+                        "  -> at org.mockitousage.debugging.InvocationsPrinterTest.triggerInteraction(InvocationsPrinterTest.java:34)\n" +
+                        "[Mockito] Unused stubbings of: mock\n" +
+                        " 1. mock.simpleMethod(\"a\");\n" +
+                        "  - stubbed -> at org.mockitousage.debugging.InvocationsPrinterTest.triggerStubbing(InvocationsPrinterTest.java:62)\n"));
+    }
+
+    private void triggerInteraction() {
+        mock.otherMethod();
+    }
+
+    private void triggerStubbing() {
+        when(mock.simpleMethod("a")).thenReturn("x");
+    }
+}
diff --git a/src/test/java/org/mockitousage/debugging/NewMockito.java b/src/test/java/org/mockitousage/debugging/NewMockito.java
new file mode 100644
index 0000000..e8cf272
--- /dev/null
+++ b/src/test/java/org/mockitousage/debugging/NewMockito.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.debugging;
+
+import org.mockito.Mockito;
+import org.mockito.MockitoDebugger;
+import org.mockito.internal.debugging.MockitoDebuggerImpl;
+
+//TODO get rid when debug() finally is out
+public class NewMockito extends Mockito {
+
+    public static MockitoDebugger debug() {
+        return new MockitoDebuggerImpl();
+    }
+}
diff --git a/src/test/java/org/mockitousage/debugging/VerboseLoggingOfInvocationsOnMockTest.java b/src/test/java/org/mockitousage/debugging/VerboseLoggingOfInvocationsOnMockTest.java
new file mode 100644
index 0000000..df985ce
--- /dev/null
+++ b/src/test/java/org/mockitousage/debugging/VerboseLoggingOfInvocationsOnMockTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.debugging;
+
+import org.assertj.core.api.Assertions;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.*;
+
+/**
+ * Tests the verbose logging of invocation on mock methods.
+ *
+ * BEWARE: These tests rely on mocking the standard output. While in a
+ * single-threaded environment the Before/After-contract ensures, that the
+ * original output stream is restored, there is no guarantee for this
+ * in the parallel setting.
+ * Maybe, the test class should be @Ignore'd by default ...
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class VerboseLoggingOfInvocationsOnMockTest {
+
+    private ByteArrayOutputStream output;
+    private PrintStream original;
+
+    @Mock UnrelatedClass unrelatedMock;
+
+    @Before
+    public void setUp() {
+        original = System.out;
+        output = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(output));
+    }
+
+    @After
+    public void tearDown() {
+        System.setOut(original);
+    }
+
+    @Test
+    public void shouldNotPrintInvocationOnMockWithoutSetting() {
+        // given
+        Foo foo = mock(Foo.class, withSettings().verboseLogging());
+
+        // when
+        foo.giveMeSomeString("Klipsch");
+        unrelatedMock.unrelatedMethod("Apple");
+
+        // then
+        Assertions.assertThat(printed())
+                .doesNotContain(mockName(unrelatedMock))
+                .doesNotContain("unrelatedMethod")
+                .doesNotContain("Apple");
+    }
+
+    @Test
+    public void shouldPrintUnstubbedInvocationOnMockToStdOut() {
+        // given
+        Foo foo = mock(Foo.class, withSettings().verboseLogging());
+
+        // when
+        foo.doSomething("Klipsch");
+
+        // then
+        Assertions.assertThat(printed())
+                .contains(getClass().getName())
+                .contains(mockName(foo))
+                .contains("doSomething")
+                .contains("Klipsch");
+    }
+
+    @Test
+    public void shouldPrintStubbedInvocationOnMockToStdOut() {
+        // given
+        Foo foo = mock(Foo.class, withSettings().verboseLogging());
+        given(foo.giveMeSomeString("Klipsch")).willReturn("earbuds");
+
+        // when
+        foo.giveMeSomeString("Klipsch");
+
+        // then
+        Assertions.assertThat(printed())
+                .contains(getClass().getName())
+                .contains(mockName(foo))
+                .contains("giveMeSomeString")
+                .contains("Klipsch")
+                .contains("earbuds");
+    }
+
+    @Test
+    public void shouldPrintThrowingInvocationOnMockToStdOut() {
+        // given
+        Foo foo = mock(Foo.class, withSettings().verboseLogging());
+        doThrow(new ThirdPartyException()).when(foo).doSomething("Klipsch");
+
+        try {
+            // when
+            foo.doSomething("Klipsch");
+            fail("Exception excepted.");
+        } catch (ThirdPartyException e) {
+            // then
+            Assertions.assertThat(printed())
+                    .contains(getClass().getName())
+                    .contains(mockName(foo))
+                    .contains("doSomething")
+                    .contains("Klipsch")
+                    .contains(ThirdPartyException.class.getName());
+        }
+    }
+
+    @Test
+    public void shouldPrintRealInvocationOnSpyToStdOut() {
+        // given
+        FooImpl fooSpy = mock(FooImpl.class,
+                withSettings().spiedInstance(new FooImpl()).verboseLogging());
+        doCallRealMethod().when(fooSpy).doSomething("Klipsch");
+
+        // when
+        fooSpy.doSomething("Klipsch");
+
+        // then
+        Assertions.assertThat(printed())
+                .contains(getClass().getName())
+                .contains(mockName(fooSpy))
+                .contains("doSomething")
+                .contains("Klipsch");
+    }
+
+    @Test
+    public void usage() {
+        // given
+        Foo foo = mock(Foo.class, withSettings().verboseLogging());
+        given(foo.giveMeSomeString("Apple")).willReturn(
+                "earbuds");
+
+        // when
+        foo.giveMeSomeString("Shure");
+        foo.giveMeSomeString("Apple");
+        foo.doSomething("Klipsch");
+    }
+
+    private String printed() {
+        return output.toString();
+    }
+
+    private String mockName(Object mock) {
+        return MockUtil.getMockName(mock).toString();
+    }
+
+    private static class UnrelatedClass {
+        void unrelatedMethod(String anotherStringValue) {
+        }
+    }
+
+    /**
+     * An exception that isn't defined by Mockito or the JDK and therefore does
+     * not appear in the logging result by chance alone.
+     */
+    static class ThirdPartyException extends RuntimeException {
+        private static final long serialVersionUID = 2160445705646210847L;
+    }
+
+    static class FooImpl implements Foo {
+        public String giveMeSomeString(String param) {
+            return null;
+        }
+
+        public void doSomething(String param) {
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/debugging/VerificationListenerCallBackTest.java b/src/test/java/org/mockitousage/debugging/VerificationListenerCallBackTest.java
new file mode 100644
index 0000000..90ce59b
--- /dev/null
+++ b/src/test/java/org/mockitousage/debugging/VerificationListenerCallBackTest.java
@@ -0,0 +1,186 @@
+package org.mockitousage.debugging;
+
+import org.assertj.core.api.Condition;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.mockito.Mockito;
+import org.mockito.MockitoFramework;
+import org.mockito.StateMaster;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.listeners.VerificationListener;
+import org.mockito.verification.VerificationEvent;
+import org.mockito.verification.VerificationMode;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.Method;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.*;
+
+public class VerificationListenerCallBackTest extends TestBase {
+
+    @After
+    public void clearListeners() {
+        new StateMaster().clearMockitoListeners();
+    }
+
+    @Test
+    public void should_call_single_listener_on_verify() throws NoSuchMethodException {
+        //given
+        RememberingListener listener = new RememberingListener();
+        MockitoFramework mockitoFramework = Mockito.framework();
+        mockitoFramework.addListener(listener);
+
+        Method invocationWanted = Foo.class.getDeclaredMethod("doSomething", String.class);
+        Foo foo = mock(Foo.class);
+
+        //when
+        VerificationMode never = never();
+        verify(foo, never).doSomething("");
+
+        //then
+        assertThat(listener).is(notifiedFor(foo, never, invocationWanted));
+    }
+
+    @Test
+    public void should_call_all_listeners_on_verify() throws NoSuchMethodException {
+        //given
+        RememberingListener listener1 = new RememberingListener();
+        RememberingListener2 listener2 = new RememberingListener2();
+        Mockito.framework().addListener(listener1).addListener(listener2);
+
+        Method invocationWanted = Foo.class.getDeclaredMethod("doSomething", String.class);
+        Foo foo = mock(Foo.class);
+
+        //when
+        VerificationMode never = never();
+        verify(foo, never).doSomething("");
+
+        //then
+        assertThat(listener1).is(notifiedFor(foo, never, invocationWanted));
+        assertThat(listener2).is(notifiedFor(foo, never, invocationWanted));
+    }
+
+    @Test
+    public void should_not_call_listener_when_verify_was_called_incorrectly() {
+        //when
+        VerificationListener listener = mock(VerificationListener.class);
+        framework().addListener(listener);
+        Foo foo = null;
+
+        try {
+            verify(foo).doSomething("");
+            fail("Exception expected.");
+        } catch (Exception e) {
+            //then
+            verify(listener, never()).onVerification(any(VerificationEvent.class));
+        }
+    }
+
+    @Test
+    public void should_notify_when_verification_throws_type_error() {
+        //given
+        RememberingListener listener = new RememberingListener();
+        MockitoFramework mockitoFramework = Mockito.framework();
+        mockitoFramework.addListener(listener);
+        Foo foo = mock(Foo.class);
+
+        //when
+        try {
+            verify(foo).doSomething("");
+            fail("Exception expected.");
+        } catch (Throwable e) {
+            //then
+            assertThat(listener.cause).isInstanceOf(MockitoAssertionError.class);
+        }
+    }
+
+    @Test
+    public void should_notify_when_verification_throws_runtime_exception() {
+        //given
+        RememberingListener listener = new RememberingListener();
+        MockitoFramework mockitoFramework = Mockito.framework();
+        mockitoFramework.addListener(listener);
+        Foo foo = mock(Foo.class);
+
+        //when
+        try {
+            verify(foo, new RuntimeExceptionVerificationMode()).doSomething("");
+            fail("Exception expected.");
+        } catch (Throwable e) {
+            //then
+            assertThat(listener.cause).isInstanceOf(RuntimeException.class);
+        }
+    }
+
+    @Test
+    public void should_call_verification_listeners() {
+        //given
+        RememberingListener listener = new RememberingListener();
+        MockitoFramework mockitoFramework = Mockito.framework();
+        mockitoFramework.addListener(listener);
+        JUnitCore runner = new JUnitCore();
+
+        //when
+        runner.run(VerificationListenerSample.class);
+
+        //then
+        assertThat(listener.mock).isNotNull();
+        assertThat(listener.mode).isEqualToComparingFieldByField(times(1));
+    }
+
+    public static class VerificationListenerSample {
+        @Test
+        public void verificationTest() {
+            Foo foo = mock(Foo.class);
+            foo.doSomething("");
+            verify(foo).doSomething("");
+        }
+    }
+
+    private static class RememberingListener implements VerificationListener {
+        Object mock;
+        VerificationMode mode;
+        VerificationData data;
+        Throwable cause;
+
+        @Override
+        public void onVerification(VerificationEvent verificationEvent) {
+            this.mock = verificationEvent.getMock();
+            this.mode = verificationEvent.getMode();
+            this.data = verificationEvent.getData();
+            this.cause = verificationEvent.getVerificationError();
+        }
+    }
+
+    private static class RememberingListener2 extends RememberingListener {
+
+    }
+
+    private static Condition<RememberingListener> notifiedFor(final Object mock, final VerificationMode mode, final Method wantedMethod) {
+        return new Condition<RememberingListener>() {
+            public boolean matches(RememberingListener listener) {
+                assertThat(listener.mock).isEqualTo(mock);
+                assertThat(listener.mode).isEqualTo(mode);
+                assertThat(listener.data.getTarget().getInvocation().getMethod()).isEqualTo(wantedMethod);
+
+                return true;
+            }
+        };
+    }
+
+    private static class RuntimeExceptionVerificationMode implements VerificationMode {
+        @Override
+        public void verify(VerificationData data) {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public VerificationMode description(String description) {
+            return null;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/examples/use/Article.java b/src/test/java/org/mockitousage/examples/use/Article.java
new file mode 100644
index 0000000..6c0d360
--- /dev/null
+++ b/src/test/java/org/mockitousage/examples/use/Article.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.examples.use;
+
+public class Article {
+
+    private int numberOfRelatedArticles;
+
+    public int getNumberOfRelatedArticles() {
+        return numberOfRelatedArticles;
+    }
+
+    public void setNumberOfRelatedArticles(int numberOfRelatedArticles) {
+        this.numberOfRelatedArticles = numberOfRelatedArticles;
+    }
+}
diff --git a/src/test/java/org/mockitousage/examples/use/ArticleCalculator.java b/src/test/java/org/mockitousage/examples/use/ArticleCalculator.java
new file mode 100644
index 0000000..8a96f36
--- /dev/null
+++ b/src/test/java/org/mockitousage/examples/use/ArticleCalculator.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.examples.use;
+
+public interface ArticleCalculator {
+    int countArticles(String newspaper);
+    int countArticlesInPolish(String newspaper);
+    int countNumberOfRelatedArticles(Article article);
+    int countAllArticles(String ... publications);
+}
diff --git a/src/test/java/org/mockitousage/examples/use/ArticleDatabase.java b/src/test/java/org/mockitousage/examples/use/ArticleDatabase.java
new file mode 100644
index 0000000..7041f54
--- /dev/null
+++ b/src/test/java/org/mockitousage/examples/use/ArticleDatabase.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.examples.use;
+
+import java.util.List;
+
+public class ArticleDatabase {
+
+    public void updateNumberOfArticles(String newspaper, int articles) {
+    }
+
+    public void updateNumberOfPolishArticles(String newspaper, int polishArticles) {
+    }
+
+    public void updateNumberOfEnglishArticles(String newspaper, int i) {
+    }
+
+    public List<Article> getArticlesFor(String string) {
+        return null;
+    }
+
+    public void save(Article article) {
+    }
+}
diff --git a/src/test/java/org/mockitousage/examples/use/ArticleManager.java b/src/test/java/org/mockitousage/examples/use/ArticleManager.java
new file mode 100644
index 0000000..6b6acd9
--- /dev/null
+++ b/src/test/java/org/mockitousage/examples/use/ArticleManager.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.examples.use;
+
+import java.util.List;
+
+public class ArticleManager {
+
+    private final ArticleCalculator calculator;
+    private final ArticleDatabase database;
+
+    public ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {
+        this.calculator = calculator;
+        this.database = database;
+    }
+
+    public void updateArticleCounters(String newspaper) {
+        int articles = calculator.countArticles(newspaper);
+        int polishArticles = calculator.countArticlesInPolish(newspaper);
+
+        database.updateNumberOfArticles(newspaper, articles);
+        database.updateNumberOfPolishArticles(newspaper, polishArticles);
+        database.updateNumberOfEnglishArticles(newspaper, articles - polishArticles);
+    }
+
+    public void updateRelatedArticlesCounters(String newspaper) {
+        List<Article> articles = database.getArticlesFor("Guardian");
+        for (Article article : articles) {
+            int numberOfRelatedArticles = calculator.countNumberOfRelatedArticles(article);
+            article.setNumberOfRelatedArticles(numberOfRelatedArticles);
+            database.save(article);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/examples/use/ExampleTest.java b/src/test/java/org/mockitousage/examples/use/ExampleTest.java
new file mode 100644
index 0000000..87b400c
--- /dev/null
+++ b/src/test/java/org/mockitousage/examples/use/ExampleTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.examples.use;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.Arrays;
+
+import static org.mockito.Mockito.*;
+
+public class ExampleTest {
+
+    @Rule public MockitoRule rule = MockitoJUnit.rule();
+
+    @Mock private ArticleCalculator mockCalculator;
+    @Mock private ArticleDatabase mockDatabase;
+
+    @InjectMocks private ArticleManager articleManager;
+
+    @Test
+    public void managerCountsArticlesAndSavesThemInTheDatabase() {
+        when(mockCalculator.countArticles("Guardian")).thenReturn(12);
+        when(mockCalculator.countArticlesInPolish(anyString())).thenReturn(5);
+
+        articleManager.updateArticleCounters("Guardian");
+
+        verify(mockDatabase).updateNumberOfArticles("Guardian", 12);
+        verify(mockDatabase).updateNumberOfPolishArticles("Guardian", 5);
+        verify(mockDatabase).updateNumberOfEnglishArticles("Guardian", 7);
+    }
+
+    @Test
+    public void managerCountsArticlesUsingCalculator() {
+        articleManager.updateArticleCounters("Guardian");
+
+        verify(mockCalculator).countArticles("Guardian");
+        verify(mockCalculator).countArticlesInPolish("Guardian");
+    }
+
+    @Test
+    public void managerSavesArticlesInTheDatabase() {
+        articleManager.updateArticleCounters("Guardian");
+
+        verify(mockDatabase).updateNumberOfArticles("Guardian", 0);
+        verify(mockDatabase).updateNumberOfPolishArticles("Guardian", 0);
+        verify(mockDatabase).updateNumberOfEnglishArticles("Guardian", 0);
+    }
+
+    @Test
+    public void managerUpdatesNumberOfRelatedArticles() {
+        Article articleOne = new Article();
+        Article articleTwo = new Article();
+        Article articleThree = new Article();
+
+        when(mockCalculator.countNumberOfRelatedArticles(articleOne)).thenReturn(1);
+        when(mockCalculator.countNumberOfRelatedArticles(articleTwo)).thenReturn(12);
+        when(mockCalculator.countNumberOfRelatedArticles(articleThree)).thenReturn(0);
+
+        when(mockDatabase.getArticlesFor("Guardian")).thenReturn(Arrays.asList(articleOne, articleTwo, articleThree));
+
+        articleManager.updateRelatedArticlesCounters("Guardian");
+
+        verify(mockDatabase).save(articleOne);
+        verify(mockDatabase).save(articleTwo);
+        verify(mockDatabase).save(articleThree);
+    }
+
+    @Test
+    public void shouldPersistRecalculatedArticle() {
+        Article articleOne = new Article();
+        Article articleTwo = new Article();
+
+        when(mockCalculator.countNumberOfRelatedArticles(articleOne)).thenReturn(1);
+        when(mockCalculator.countNumberOfRelatedArticles(articleTwo)).thenReturn(12);
+
+        when(mockDatabase.getArticlesFor("Guardian")).thenReturn(Arrays.asList(articleOne, articleTwo));
+
+        articleManager.updateRelatedArticlesCounters("Guardian");
+
+        InOrder inOrder = inOrder(mockDatabase, mockCalculator);
+
+        inOrder.verify(mockCalculator).countNumberOfRelatedArticles((Article) anyObject());
+        inOrder.verify(mockDatabase, atLeastOnce()).save((Article) anyObject());
+    }
+}
diff --git a/src/test/java/org/mockitousage/internal/debugging/LocationImplTest.java b/src/test/java/org/mockitousage/internal/debugging/LocationImplTest.java
new file mode 100644
index 0000000..4ecf5f7
--- /dev/null
+++ b/src/test/java/org/mockitousage/internal/debugging/LocationImplTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.internal.debugging;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.exceptions.stacktrace.StackTraceFilter;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+
+@SuppressWarnings("serial")
+public class LocationImplTest extends TestBase {
+
+    @Test
+    public void shouldLocationNotContainGetStackTraceMethod() {
+        assertThat(new LocationImpl().toString()).contains("shouldLocationNotContainGetStackTraceMethod");
+    }
+
+    @Test
+    public void shouldBeSafeInCaseForSomeReasonFilteredStackTraceIsEmpty() {
+        //given
+        StackTraceFilter filterReturningEmptyArray = new StackTraceFilter() {
+            @Override
+            public StackTraceElement[] filter(StackTraceElement[] target, boolean keepTop) {
+                return new StackTraceElement[0];
+            }
+        };
+
+        //when
+        String loc = new LocationImpl(filterReturningEmptyArray).toString();
+
+        //then
+        assertEquals("-> at <<unknown line>>", loc);
+    }
+}
diff --git a/src/test/java/org/mockitousage/internal/invocation/realmethod/CleanTraceRealMethodTest.java b/src/test/java/org/mockitousage/internal/invocation/realmethod/CleanTraceRealMethodTest.java
new file mode 100644
index 0000000..0520b00
--- /dev/null
+++ b/src/test/java/org/mockitousage/internal/invocation/realmethod/CleanTraceRealMethodTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.internal.invocation.realmethod;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.invocation.realmethod.CleanTraceRealMethod;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockitoutil.Conditions.methodInStackTraceAt;
+
+public class CleanTraceRealMethodTest extends TestBase {
+
+    @Before
+    public void keepStackTracesClean() {
+        makeStackTracesClean();
+    }
+
+    class Foo {
+
+        public String throwSomething() {
+            throw new RuntimeException();
+        }
+    }
+
+    @Test
+    public void shouldRemoveMockitoInternalsFromStackTraceWhenRealMethodThrows() throws Throwable {
+        //given
+        CleanTraceRealMethod realMethod = new CleanTraceRealMethod(new RealMethod() {
+            public Object invoke(Object target, Object[] arguments) throws Throwable {
+                return new Foo().throwSomething();
+            }
+        });
+
+        //when
+        try {
+            realMethod.invoke(null, null);
+            fail();
+        //then
+        } catch (Exception e) {
+            Assertions.assertThat(e).has(methodInStackTraceAt(0, "throwSomething"));
+            Assertions.assertThat(e).has(methodInStackTraceAt(1, "invoke"));
+            Assertions.assertThat(e).has(methodInStackTraceAt(2, "shouldRemoveMockitoInternalsFromStackTraceWhenRealMethodThrows"));
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/internal/junit/UnusedStubbingsFinderTest.java b/src/test/java/org/mockitousage/internal/junit/UnusedStubbingsFinderTest.java
new file mode 100644
index 0000000..499327e
--- /dev/null
+++ b/src/test/java/org/mockitousage/internal/junit/UnusedStubbingsFinderTest.java
@@ -0,0 +1,127 @@
+package org.mockitousage.internal.junit;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.internal.junit.UnusedStubbings;
+import org.mockito.internal.junit.UnusedStubbingsFinder;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.Collection;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+/**
+ * This unit test lives in 'org.mockitousage' package for a reason.
+ * It makes it easy to write tests that depend on the stack trace filtering logic.
+ * Long term, it would be nice to have more configurability in TestBase
+ *  to make it easy to write such unit tests in 'org.mockito.*' packages.
+ */
+public class UnusedStubbingsFinderTest extends TestBase {
+
+    UnusedStubbingsFinder finder = new UnusedStubbingsFinder();
+    @Mock IMethods mock1;
+    @Mock IMethods mock2;
+
+    @Test
+    public void no_interactions() throws Exception {
+        //expect
+        assertEquals(0, finder.getUnusedStubbings((List) asList(mock1, mock2)).size());
+        assertEquals(0, finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2)).size());
+    }
+
+    @Test
+    public void no_stubbings() throws Exception {
+        //when
+        mock1.simpleMethod();
+
+        //then
+        assertEquals(0, finder.getUnusedStubbings((List) asList(mock1, mock2)).size());
+        assertEquals(0, finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2)).size());
+    }
+
+    @Test
+    public void no_unused_stubbings() throws Exception {
+        //when
+        when(mock1.simpleMethod()).thenReturn("1");
+        mock1.simpleMethod();
+
+        //then
+        assertEquals(0, finder.getUnusedStubbings((List) asList(mock1, mock2)).size());
+        assertEquals(0, finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2)).size());
+    }
+
+    @Test
+    public void unused_stubbings() throws Exception {
+        //when
+        when(mock1.simpleMethod()).thenReturn("1");
+
+        //then
+        assertEquals(1, finder.getUnusedStubbings((List) asList(mock1, mock2)).size());
+        assertEquals(1, finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2)).size());
+    }
+
+    @Test
+    public void some_unused_stubbings() throws Exception {
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        when(mock2.simpleMethod(2)).thenReturn("2");
+        when(mock2.simpleMethod(3)).thenReturn("3");
+
+        mock2.simpleMethod(2);
+
+        //when
+        UnusedStubbings stubbings = finder.getUnusedStubbings((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(2, stubbings.size());
+        assertEquals("[mock1.simpleMethod(1); stubbed with: [Returns: 1], mock2.simpleMethod(3); stubbed with: [Returns: 3]]",
+                stubbings.toString());
+    }
+
+    @Test
+    public void some_unused_stubbings_by_location() throws Exception {
+        when(mock1.simpleMethod(1)).thenReturn("1");
+        when(mock2.simpleMethod(2)).thenReturn("2");
+        when(mock2.simpleMethod(3)).thenReturn("3");
+
+        mock2.simpleMethod(2);
+
+        //when
+        Collection stubbings = finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(2, stubbings.size());
+        assertEquals("[mock1.simpleMethod(1);, mock2.simpleMethod(3);]", stubbings.toString());
+    }
+
+    @Test
+    public void stubbing_used_by_location() throws Exception {
+        //when
+        //Emulating stubbing in the same location by putting stubbing in the same line:
+        when(mock1.simpleMethod(1)).thenReturn("1"); when(mock2.simpleMethod(1)).thenReturn("1");
+        //End of emulation
+        mock1.simpleMethod(1);
+
+        //then technically unused stubbings exist
+        assertEquals(1, finder.getUnusedStubbings((List) asList(mock1, mock2)).size());
+        //however if we consider stubbings in the same location as the same stubbing, all is used:
+        assertEquals(0, finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2)).size());
+    }
+
+    @Test
+    public void deduplicates_stubbings_by_location() throws Exception {
+        //when
+        //Emulating stubbing in the same location by putting stubbing in the same line:
+        when(mock1.simpleMethod(1)).thenReturn("1"); when(mock2.simpleMethod(1)).thenReturn("1");
+        //End of emulation
+
+        //when
+        Collection stubbings = finder.getUnusedStubbingsByLocation((List) asList(mock1, mock2));
+
+        //then
+        assertEquals(1, stubbings.size());
+    }
+}
diff --git a/src/test/java/org/mockitousage/internal/package-info.java b/src/test/java/org/mockitousage/internal/package-info.java
new file mode 100644
index 0000000..8b68cba
--- /dev/null
+++ b/src/test/java/org/mockitousage/internal/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Those unit tests exercise internals of Mockito but they are kept in {@link org.mockitousage} in order to have stack traces clean
+ * (stack traces are cleaned based on package)
+ */
+package org.mockitousage.internal;
diff --git a/src/test/java/org/mockitousage/jls/JLS_15_12_2_5Test.java b/src/test/java/org/mockitousage/jls/JLS_15_12_2_5Test.java
new file mode 100644
index 0000000..5d0b2c3
--- /dev/null
+++ b/src/test/java/org/mockitousage/jls/JLS_15_12_2_5Test.java
@@ -0,0 +1,240 @@
+package org.mockitousage.jls;
+
+import net.bytebuddy.ClassFileVersion;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+
+import static net.bytebuddy.ClassFileVersion.JAVA_V6;
+import static net.bytebuddy.ClassFileVersion.JAVA_V7;
+import static net.bytebuddy.ClassFileVersion.JAVA_V8;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+/**
+ * Illustrate differences in the JLS depending on the Java version.
+ */
+@RunWith(Enclosed.class)
+public class JLS_15_12_2_5Test {
+
+    /**
+     * The JLS §15.12.2.5 states that the compiler must chose the most specific overload in Java 6 or Java 7,
+     * but with generics in the matcher, <strong>javac</strong> selects the upper bound, which is {@code Object},
+     * as such javac selects the most generic method.
+     *
+     * https://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.12.2.5
+     * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5
+     *
+     * <blockquote>
+     *     <p>If more than one member method is both accessible and applicable to a method invocation, it is necessary to
+     *     choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses
+     *     the rule that the most specific method is chosen.</p>
+     *
+     *     <p>The informal intuition is that one method is more specific than another if any invocation handled by
+     *     the first method could be passed on to the other one without a compile-time type error.</p>
+     * </blockquote>
+     */
+    public static class JLS_15_12_2_5_Java6_Java7_Test {
+        @Before
+        public void setUp() throws Exception {
+            Assume.assumeTrue(ClassFileVersion.of(JLS_15_12_2_5_Java6_Java7_Test.class).equals(JAVA_V6)
+                              || ClassFileVersion.of(JLS_15_12_2_5_Java6_Java7_Test.class).equals(JAVA_V7));
+        }
+
+        @Test
+        public void with_single_arg() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.oneArg(isNull())).thenReturn("ok");
+
+            assertThat(mock.oneArg(null)).describedAs("Most generic method chosen for matcher " +
+                                                      "(isNull generic upper bound is Object), but null applies " +
+                                                      "to select most specific method")
+                                         .isEqualTo(null);
+        }
+
+        @Test
+        public void with_single_arg_and_matcher_cast() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.oneArg((String) isNull())).thenReturn("ok");
+
+            assertThat(mock.oneArg(null)).describedAs("Most specific method enforced for matcher via cast").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_single_arg_and_null_Object_reference() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.oneArg(isNull())).thenReturn("ok");
+
+            Object arg = null;
+            assertThat(mock.oneArg(arg)).describedAs("Most generic method chosen for matcher").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_variable_arg() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs(isNull())).thenReturn("ok");
+
+            assertThat(mock.varargs(null)).describedAs("Most generic method chosen for matcher " +
+                                                       "(isNull generic upper bound is Object), but null applies " +
+                                                       "to select most specific method")
+                                          .isEqualTo(null);
+        }
+
+        @Test
+        public void with_variable_arg_and_matcher_String_cast() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs((String) isNull())).thenReturn("ok");
+
+            assertThat(mock.varargs(null)).describedAs("Most specific method enforced for matcher via String cast").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_variable_arg_and_matcher_String_array_cast() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs((String[]) isNull())).thenReturn("ok");
+
+            assertThat(mock.varargs(null)).describedAs("Most specific method enforced for matcher via String[] cast").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_variable_arg_and_null_Object_array() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs(isNull())).thenReturn("ok");
+
+            Object[] args = null;
+            assertThat(mock.varargs(args)).describedAs("isNull matcher generic upper bound is Object").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_variable_arg_and_null_Object_arg() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs(isNull())).thenReturn("ok");
+
+            Object arg = null;
+            assertThat(mock.varargs(arg)).describedAs("isNull matcher generic upper bound is Object").isEqualTo("ok");
+        }
+    }
+
+    /**
+     * The JLS §15.12.2.5 states that the compiler must chose the most specific overload in Java 8, however the
+     * Java 8 compiler perform a type inference before selecting
+     *
+     * https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2
+     * <blockquote>
+     *     <p>Deciding whether a method is applicable will, in the case of generic methods (§8.4.4), require an analysis
+     *     of the type arguments. Type arguments may be passed explicitly or implicitly. If they are passed implicitly,
+     *     bounds of the type arguments must be inferred (§18 (Type Inference)) from the argument expressions.</p>
+     *
+     *     <p>If several applicable methods have been identified during one of the three phases of applicability
+     *     testing, then the most specific one is chosen, as specified in section §15.12.2.5.</p>
+     * </blockquote>
+     *
+     * https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1
+     * <blockquote>
+     *     <p>The definition of potential applicability goes beyond a basic arity check to also take into account
+     *     the presence and "shape" of functional interface target types. In some cases involving type argument
+     *     inference, a lambda expression appearing as a method invocation argument cannot be properly typed until
+     *     after overload resolution. These rules allow the form of the lambda expression to still be taken into
+     *     account, discarding obviously incorrect target types that might otherwise cause ambiguity errors.</p>
+     * </blockquote>
+     *
+     * https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
+     * <blockquote>
+     *     <p>One applicable method m1 is more specific than another applicable method m2, for an invocation with argument
+     *     expressions e1, ..., ek, if any of the following are true:
+     *     <ul>
+     *
+     *     <li>m2 is generic, and m1 is inferred to be more specific than m2 for argument expressions e1, ..., ek
+     *     by §18.5.4.</li>
+     *     <li>m2 is not generic, and m1 and m2 are applicable by strict or loose invocation, and where m1 has formal
+     *     parameter types S1, ..., Sn and m2 has formal parameter types T1, ..., Tn, the type Si is more specific
+     *     than Ti for argument ei for all i (1 ≤ i ≤ n, n = k).</li>
+     *     <li>m2 is not generic, and m1 and m2 are applicable by variable arity invocation, and where the first k
+     *     variable arity parameter types of m1 are S1, ..., Sk and the first k variable arity parameter types of m2
+     *     are T1, ..., Tk, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ k).
+     *     Additionally, if m2 has k+1 parameters, then the k+1'th variable arity parameter type of m1 is a subtype
+     *     of the k+1'th variable arity parameter type of m2.</li>
+     *     </ul></p>
+     *
+     *     <p>The above conditions are the only circumstances under which one method may be more specific than another.</p>
+     *
+     *     <p>A type S is more specific than a type T for any expression if S <: T (§4.10).</p>
+     * </blockquote>
+     */
+    public static class JLS_15_12_2_5_Java8_Test {
+        @Before
+        public void setUp() throws Exception {
+            Assume.assumeTrue(ClassFileVersion.of(JLS_15_12_2_5_Java8_Test.class).isAtLeast(JAVA_V8));
+        }
+
+        @Test
+        public void with_single_arg() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.oneArg(isNull())).thenReturn("ok");
+
+            assertThat(mock.oneArg(null)).describedAs("Most specific method chosen for matcher and for null").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_single_arg_and_null_Object_reference() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.oneArg(isNull())).thenReturn("ok");
+
+            Object arg = null;
+            assertThat(mock.oneArg(arg)).describedAs("not the stubbed method").isEqualTo(null);
+        }
+
+        @Test
+        public void with_variable_arg() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs(isNull())).thenReturn("ok");
+
+            assertThat(mock.varargs(null)).describedAs("Most specific method chosen for matcher and for null").isEqualTo("ok");
+        }
+
+        @Test
+        public void with_variable_arg_and_null_Object_array() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs(isNull())).thenReturn("ok");
+
+            Object[] args = null;
+            assertThat(mock.varargs(args)).describedAs("Most specific method chosen for matcher").isEqualTo(null);
+        }
+
+        @Test
+        public void with_variable_arg_and_null_Object_arg() throws Exception {
+            SingleOverload mock = mock(SingleOverload.class);
+
+            when(mock.varargs(isNull())).thenReturn("ok");
+
+            Object arg = null;
+            assertThat(mock.varargs(arg)).describedAs("Most specific method chosen for matcher").isEqualTo(null);
+        }
+
+    }
+
+    interface SingleOverload {
+        String oneArg(Object arg);
+        String oneArg(String arg);
+        String varargs(Object... args);
+        String varargs(String... args);
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/junitrule/InvalidTargetMockitoJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/InvalidTargetMockitoJUnitRuleTest.java
new file mode 100644
index 0000000..8b12605
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/InvalidTargetMockitoJUnitRuleTest.java
@@ -0,0 +1,38 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static org.junit.Assert.assertNotNull;
+
+public class InvalidTargetMockitoJUnitRuleTest {
+
+    @Rule
+    public MockitoRule mockitoJUnitRule = MockitoJUnit.rule();
+
+    @Mock
+    private Injected injected;
+
+    @InjectMocks
+    private InjectInto injectInto;
+
+    @Test
+    public void shouldInjectWithInvalidReference() throws Exception {
+        assertNotNull("Mock created", injected);
+        assertNotNull("Test object created", injectInto);
+    }
+
+    public static class Injected { }
+
+    public static class InjectInto {
+        private Injected injected;
+
+        public Injected getInjected() {
+            return injected;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/LenientJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/LenientJUnitRuleTest.java
new file mode 100644
index 0000000..292480e
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/LenientJUnitRuleTest.java
@@ -0,0 +1,39 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.quality.Strictness;
+import org.mockito.internal.junit.JUnitRule;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+
+import static org.mockito.Mockito.when;
+
+public class LenientJUnitRuleTest {
+
+    private MockitoLogger explosiveLogger = new MockitoLogger() {
+        public void log(Object what) {
+            throw new RuntimeException("Silent rule should not write anything to the logger");
+        }
+    };
+    @Mock private IMethods mock;
+
+    @Rule public MockitoRule mockitoRule = new JUnitRule(explosiveLogger, Strictness.LENIENT);
+
+    @Test public void no_warning_for_unused_stubbing() throws Exception {
+        when(mock.simpleMethod(1)).thenReturn("1");
+    }
+
+    @Test public void no_warning_for_stubbing_arg_mismatch() throws Exception {
+        when(mock.simpleMethod(1)).thenReturn("1");
+        mock.simpleMethod(2);
+    }
+
+    @Test(expected = IllegalStateException.class) public void no_warning_for_stubbing_arg_mismatch_on_failure() throws Exception {
+        when(mock.simpleMethod(1)).thenReturn("1");
+        mock.simpleMethod(2);
+        throw new IllegalStateException("hey!");
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java
new file mode 100644
index 0000000..64be8ec
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java
@@ -0,0 +1,40 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MockitoJUnitRuleTest {
+
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private Injected injected;
+
+    @InjectMocks
+    private InjectInto injectInto;
+
+    @Test
+    public void testInjectMocks() throws Exception {
+        assertNotNull("Mock created", injected);
+        assertNotNull("Object created", injectInto);
+        assertEquals("A injected into B", injected, injectInto.getInjected());
+    }
+
+    public static class Injected { }
+
+    public static class InjectInto {
+        private Injected injected;
+
+        public Injected getInjected() {
+            return injected;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/MutableStrictJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/MutableStrictJUnitRuleTest.java
new file mode 100644
index 0000000..d7d4601
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/MutableStrictJUnitRuleTest.java
@@ -0,0 +1,71 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+import org.mockitousage.IMethods;
+import org.mockitoutil.JUnitResultAssert;
+
+import static org.mockito.Mockito.when;
+
+public class MutableStrictJUnitRuleTest {
+
+    JUnitCore runner = new JUnitCore();
+
+    @Test public void rule_can_be_changed_to_strict() throws Throwable {
+        //when
+        Result result = runner.run(LenientByDefault.class);
+
+        //then
+        JUnitResultAssert.assertThat(result)
+                .succeeds(1)
+                .fails(1, RuntimeException.class);
+    }
+
+    @Test public void rule_can_be_changed_to_lenient() throws Throwable {
+        //when
+        Result result = runner.run(StrictByDefault.class);
+
+        //then
+        JUnitResultAssert.assertThat(result)
+                .succeeds(1)
+                .fails(1, RuntimeException.class);
+    }
+
+    public static class LenientByDefault {
+        @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.LENIENT);
+        @Mock IMethods mock;
+
+        @Test public void unused_stub() throws Throwable {
+            when(mock.simpleMethod()).thenReturn("1");
+        }
+
+        @Test public void unused_stub_with_strictness() throws Throwable {
+            //making Mockito strict only for this test method
+            mockito.strictness(Strictness.STRICT_STUBS);
+
+            when(mock.simpleMethod()).thenReturn("1");
+        }
+    }
+
+    public static class StrictByDefault {
+        @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+        @Mock IMethods mock;
+
+        @Test public void unused_stub() throws Throwable {
+            when(mock.simpleMethod()).thenReturn("1");
+        }
+
+        @Test public void unused_stub_with_lenient() throws Throwable {
+            //making Mockito lenient only for this test method
+            mockito.strictness(Strictness.LENIENT);
+
+            when(mock.simpleMethod()).thenReturn("1");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/RuleTestWithFactoryMethodTest.java b/src/test/java/org/mockitousage/junitrule/RuleTestWithFactoryMethodTest.java
new file mode 100644
index 0000000..d2af2d3
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/RuleTestWithFactoryMethodTest.java
@@ -0,0 +1,43 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class RuleTestWithFactoryMethodTest {
+
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private Injected injected;
+
+    @InjectMocks
+    private InjectInto injectInto;
+
+    @Test
+    public void testInjectMocks() throws Exception {
+        assertNotNull("Mock created", injected);
+        assertNotNull("Object created", injectInto);
+        assertEquals("A injected into B", injected, injectInto.getInjected());
+
+    }
+
+    public static class Injected {
+    }
+
+    public static class InjectInto {
+
+        private Injected injected;
+
+        public Injected getInjected() {
+            return injected;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/RuleTestWithParameterConstructorTest.java b/src/test/java/org/mockitousage/junitrule/RuleTestWithParameterConstructorTest.java
new file mode 100644
index 0000000..f3798bf
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/RuleTestWithParameterConstructorTest.java
@@ -0,0 +1,43 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class RuleTestWithParameterConstructorTest {
+
+	 @Rule
+	 public MockitoRule mockitoJUnitRule = MockitoJUnit.rule();
+
+    @Mock
+    private Injected injected;
+
+    @InjectMocks
+    private InjectInto injectInto;
+
+    @Test
+    public void testInjectMocks() throws Exception {
+        assertNotNull("Mock created", injected);
+        assertNotNull("Object created", injectInto);
+        assertEquals("A injected into B", injected, injectInto.getInjected());
+
+    }
+
+    public static class Injected {
+    }
+
+    public static class InjectInto {
+
+        private Injected injected;
+
+        public Injected getInjected() {
+            return injected;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/StrictJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/StrictJUnitRuleTest.java
new file mode 100644
index 0000000..f2dc2dd
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/StrictJUnitRuleTest.java
@@ -0,0 +1,161 @@
+package org.mockitousage.junitrule;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.quality.Strictness;
+import org.mockito.exceptions.misusing.PotentialStubbingProblem;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.junit.MockitoJUnit;
+import org.mockitousage.IMethods;
+import org.mockitoutil.SafeJUnitRule;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.willReturn;
+import static org.mockito.Mockito.*;
+import static org.mockitoutil.TestBase.filterLineNo;
+
+public class StrictJUnitRuleTest {
+
+    @Rule public SafeJUnitRule rule = new SafeJUnitRule(MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS));
+
+    @Mock IMethods mock;
+    @Mock IMethods mock2;
+
+    @Test public void ok_when_no_stubbings() throws Throwable {
+        mock.simpleMethod();
+        verify(mock).simpleMethod();
+    }
+
+    @Test public void ok_when_all_stubbings_used() throws Throwable {
+        given(mock.simpleMethod(10)).willReturn("foo");
+        mock.simpleMethod(10);
+    }
+
+    @Test public void ok_when_used_and_mismatched_argument() throws Throwable {
+        given(mock.simpleMethod(10)).willReturn("foo");
+        mock.simpleMethod(10);
+        mock.simpleMethod(15);
+    }
+
+    @Test public void fails_when_unused_stubbings() throws Throwable {
+        //expect
+        rule.expectFailure(UnnecessaryStubbingException.class);
+
+        //when
+        given(mock.simpleMethod(10)).willReturn("foo");
+        mock2.simpleMethod(10);
+    }
+
+    @Test public void test_failure_trumps_unused_stubbings() throws Throwable {
+        //expect
+        rule.expectFailure(AssertionError.class, "x");
+
+        //when
+        given(mock.simpleMethod(10)).willReturn("foo");
+        mock.otherMethod();
+
+        throw new AssertionError("x");
+    }
+
+    @Test public void why_do_return_syntax_is_useful() throws Throwable {
+        //Trade-off of Mockito strictness documented in test
+
+        //expect
+        rule.expectFailure(PotentialStubbingProblem.class);
+
+        //when
+        when(mock.simpleMethod(10)).thenReturn("10");
+        when(mock.simpleMethod(20)).thenReturn("20");
+    }
+
+    @Test public void fails_fast_when_stubbing_invoked_with_different_argument() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                Assertions.assertThat(t).isInstanceOf(PotentialStubbingProblem.class);
+                assertEquals(filterLineNo("\n" +
+                                "Strict stubbing argument mismatch. Please check:\n" +
+                                " - this invocation of 'simpleMethod' method:\n" +
+                                "    mock.simpleMethod(15);\n" +
+                                "    -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" +
+                                " - has following stubbing(s) with different arguments:\n" +
+                                "    1. mock.simpleMethod(20);\n" +
+                                "      -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" +
+                                "    2. mock.simpleMethod(30);\n" +
+                                "      -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" +
+                                "Typically, stubbing argument mismatch indicates user mistake when writing tests.\n" +
+                                "Mockito fails early so that you can debug potential problem easily.\n" +
+                                "However, there are legit scenarios when this exception generates false negative signal:\n" +
+                                "  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API\n" +
+                                "    Please use 'will().given()' or 'doReturn().when()' API for stubbing.\n" +
+                                "  - stubbed method is intentionally invoked with different arguments by code under test\n" +
+                                "    Please use 'default' or 'silent' JUnit Rule.\n" +
+                                "For more information see javadoc for PotentialStubbingProblem class."),
+                        filterLineNo(t.getMessage()));
+            }
+        });
+
+        //when stubbings in the test code:
+        willReturn("10").given(mock).simpleMethod(10) ;  //used
+        willReturn("20").given(mock).simpleMethod(20) ;  //unused
+        willReturn("30").given(mock).simpleMethod(30) ;  //unused
+
+        //then
+        mock.otherMethod(); //ok, different method
+        mock.simpleMethod(10); //ok, stubbed with this argument
+
+        //invocation in the code under test uses different argument and should fail immediately
+        //this helps with debugging and is essential for Mockito strictness
+        mock.simpleMethod(15);
+    }
+
+    @Test public void verify_no_more_interactions_ignores_stubs() throws Throwable {
+        //when stubbing in test:
+        given(mock.simpleMethod(10)).willReturn("foo");
+
+        //and code under test does:
+        mock.simpleMethod(10); //implicitly verifies the stubbing
+        mock.otherMethod();
+
+        //and in test we:
+        verify(mock).otherMethod();
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test public void unused_stubs_with_multiple_mocks() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertEquals(filterLineNo("\n" +
+                        "Unnecessary stubbings detected.\n" +
+                        "Clean & maintainable test code requires zero unnecessary code.\n" +
+                        "Following stubbings are unnecessary (click to navigate to relevant line of code):\n" +
+                        "  1. -> at org.mockitousage.junitrule.StrictJUnitRuleTest.unused_stubs_with_multiple_mocks(StrictJUnitRuleTest.java:0)\n" +
+                        "  2. -> at org.mockitousage.junitrule.StrictJUnitRuleTest.unused_stubs_with_multiple_mocks(StrictJUnitRuleTest.java:0)\n" +
+                        "Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class."), filterLineNo(t.getMessage()));
+            }
+        });
+
+        //when test has
+        given(mock.simpleMethod(10)).willReturn("foo");
+        given(mock2.simpleMethod(20)).willReturn("foo");
+
+        given(mock.otherMethod()).willReturn("foo"); //used and should not be reported
+
+        //and code has
+        mock.otherMethod();
+        mock2.booleanObjectReturningMethod();
+    }
+
+    @Test public void rule_validates_mockito_usage() throws Throwable {
+        //expect
+        rule.expectFailure(UnfinishedVerificationException.class);
+
+        //when test contains unfinished verification
+        verify(mock);
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/StubbingWarningsJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/StubbingWarningsJUnitRuleTest.java
new file mode 100644
index 0000000..4ddf5b7
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/StubbingWarningsJUnitRuleTest.java
@@ -0,0 +1,203 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.quality.Strictness;
+import org.mockito.internal.junit.JUnitRule;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockitousage.IMethods;
+import org.mockitoutil.SafeJUnitRule;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+import static org.mockitoutil.TestBase.filterLineNo;
+
+public class StubbingWarningsJUnitRuleTest {
+
+    private SimpleMockitoLogger logger = new SimpleMockitoLogger();
+    @Rule public SafeJUnitRule rule = new SafeJUnitRule(new JUnitRule(logger, Strictness.WARN));
+    @Mock IMethods mock;
+
+    @Test
+    public void no_unused_stubs_reported_on_failure() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertEquals("x", t.getMessage());
+                assertTrue(logger.getLoggedInfo().isEmpty());
+            }
+        });
+
+        //when
+        declareStubbing(mock);
+        throw new AssertionError("x");
+    }
+
+    @Test
+    public void stubbing_arg_mismatch_on_failure() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertEquals("x", t.getMessage());
+                assertEquals(
+                    "[MockitoHint] StubbingWarningsJUnitRuleTest.stubbing_arg_mismatch_on_failure (see javadoc for MockitoHint):\n" +
+                    "[MockitoHint] 1. Unused... -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.declareStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                    "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.useStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n",
+                        filterLineNo(logger.getLoggedInfo()));
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a");
+        useStubbingWithArg(mock, "b");
+        throw new AssertionError("x");
+    }
+
+    @Test public void no_stubbing_arg_mismatch_when_no_mismatch_on_fail() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertEquals("x", t.getMessage());
+                assertTrue(logger.getLoggedInfo().isEmpty());
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a");
+        useStubbingWithArg(mock, "a");
+        throw new AssertionError("x");
+    }
+
+    @Test
+    public void no_stubbing_warning_on_pass() throws Throwable {
+        //expect
+        rule.expectSuccess(new Runnable() {
+            public void run() {
+                assertTrue(logger.isEmpty());
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a");
+        useStubbingWithArg(mock, "a");
+    }
+
+    @Test
+    public void multiple_stubbing_arg_mismatch_on_failure() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertEquals("x", t.getMessage());
+                assertEquals(
+                    "[MockitoHint] StubbingWarningsJUnitRuleTest.multiple_stubbing_arg_mismatch_on_failure (see javadoc for MockitoHint):\n" +
+                    "[MockitoHint] 1. Unused... -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.declareStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                    "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.useStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                    "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.useStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                    "[MockitoHint] 2. Unused... -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.declareStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                    "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.useStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                    "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.useStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n",
+                        filterLineNo(logger.getLoggedInfo()));
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a");
+        declareStubbingWithArg(mock, "b");
+
+        useStubbingWithArg(mock, "c");
+        useStubbingWithArg(mock, "d");
+
+        throw new AssertionError("x");
+    }
+
+    @Test
+    public void reports_only_mismatching_stubs() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+            assertEquals("x", t.getMessage());
+            assertEquals(
+                "[MockitoHint] StubbingWarningsJUnitRuleTest.reports_only_mismatching_stubs (see javadoc for MockitoHint):\n" +
+                "[MockitoHint] 1. Unused... -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.declareStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n" +
+                "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.useStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n",
+                    filterLineNo(logger.getLoggedInfo()));
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a"); // <-- used
+        declareStubbingWithArg(mock, "b"); // <-- unused
+
+        useStubbingWithArg(mock, "a");
+        useStubbingWithArg(mock, "d"); // <-- arg mismatch
+
+        throw new AssertionError("x");
+    }
+
+    @Test
+    public void no_mismatch_when_stub_was_used() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertEquals("x", t.getMessage());
+                assertTrue(logger.getLoggedInfo().isEmpty());
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a");
+
+        useStubbingWithArg(mock, "a");
+        useStubbingWithArg(mock, "d"); // <-- arg mismatch, but the stub was already used
+
+        throw new AssertionError("x");
+    }
+
+    @Test
+    public void no_stubbing_arg_mismatch_on_pass() throws Throwable {
+        //expect
+        rule.expectSuccess(new Runnable() {
+            public void run() {
+                assertEquals(
+                    "[MockitoHint] StubbingWarningsJUnitRuleTest.no_stubbing_arg_mismatch_on_pass (see javadoc for MockitoHint):\n" +
+                    "[MockitoHint] 1. Unused -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.declareStubbingWithArg(StubbingWarningsJUnitRuleTest.java:0)\n",
+                        filterLineNo(logger.getLoggedInfo()));
+            }
+        });
+
+        //when
+        declareStubbingWithArg(mock, "a");
+        useStubbingWithArg(mock, "b");
+    }
+
+    @Test
+    public void warns_about_unused_stubs_when_passed() throws Throwable {
+        //expect
+        rule.expectSuccess(new Runnable() {
+            public void run() {
+                assertEquals(
+                    "[MockitoHint] StubbingWarningsJUnitRuleTest.warns_about_unused_stubs_when_passed (see javadoc for MockitoHint):\n" +
+                    "[MockitoHint] 1. Unused -> at org.mockitousage.junitrule.StubbingWarningsJUnitRuleTest.declareStubbing(StubbingWarningsJUnitRuleTest.java:0)\n",
+                        filterLineNo(logger.getLoggedInfo()));
+
+            }
+        });
+
+        //when
+        declareStubbing(mock);
+    }
+
+    private static void declareStubbingWithArg(IMethods mock, String arg) {
+        when(mock.simpleMethod(arg)).thenReturn("bar");
+    }
+
+    private static void declareStubbing(IMethods mock) {
+        when(mock.simpleMethod("foo")).thenReturn("bar");
+    }
+
+    private void useStubbingWithArg(IMethods mock, String arg) {
+        mock.simpleMethod(arg);
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrule/StubbingWarningsMultiThreadingTest.java b/src/test/java/org/mockitousage/junitrule/StubbingWarningsMultiThreadingTest.java
new file mode 100644
index 0000000..a01a009
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/StubbingWarningsMultiThreadingTest.java
@@ -0,0 +1,65 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.quality.Strictness;
+import org.mockito.internal.junit.JUnitRule;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockitousage.IMethods;
+import org.mockitoutil.ConcurrentTesting;
+import org.mockitoutil.SafeJUnitRule;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+import static org.mockitoutil.TestBase.filterLineNo;
+
+public class StubbingWarningsMultiThreadingTest {
+
+    private SimpleMockitoLogger logger = new SimpleMockitoLogger();
+    @Rule public SafeJUnitRule rule = new SafeJUnitRule(new JUnitRule(logger, Strictness.WARN));
+    @Mock IMethods mock;
+
+    @Test public void using_stubbing_from_different_thread() throws Throwable {
+        //expect no warnings
+        rule.expectSuccess(new Runnable() {
+            public void run() {
+                assertTrue(logger.getLoggedInfo().isEmpty());
+            }
+        });
+
+        //when stubbing is declared
+        when(mock.simpleMethod()).thenReturn("1");
+        //and used from a different thread
+        ConcurrentTesting.inThread(new Runnable() {
+                    public void run() {
+                        mock.simpleMethod();
+                    }
+                });
+    }
+
+    @Test public void unused_stub_from_different_thread() throws Throwable {
+        //expect warnings
+        rule.expectSuccess(new Runnable() {
+            public void run() {
+                assertEquals(
+                    "[MockitoHint] StubbingWarningsMultiThreadingTest.unused_stub_from_different_thread (see javadoc for MockitoHint):\n" +
+                    "[MockitoHint] 1. Unused -> at org.mockitousage.junitrule.StubbingWarningsMultiThreadingTest.unused_stub_from_different_thread(StubbingWarningsMultiThreadingTest.java:0)\n",
+                        filterLineNo(logger.getLoggedInfo()));
+            }
+        });
+
+        //when stubbings are declared
+        when(mock.simpleMethod(1)).thenReturn("1");
+        when(mock.simpleMethod(2)).thenReturn("2");
+
+        //and one of the stubbings is used from a different thread
+        ConcurrentTesting.inThread(new Runnable() {
+            public void run() {
+                mock.simpleMethod(1);
+            }
+        });
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/junitrule/VerificationCollectorImplTest.java b/src/test/java/org/mockitousage/junitrule/VerificationCollectorImplTest.java
new file mode 100644
index 0000000..e6a1650
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrule/VerificationCollectorImplTest.java
@@ -0,0 +1,121 @@
+package org.mockitousage.junitrule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.VerificationCollector;
+import org.mockitousage.IMethods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.*;
+
+public class VerificationCollectorImplTest {
+
+    @Test
+    public void should_not_throw_any_exceptions_when_verifications_are_succesful() {
+        VerificationCollector collector = MockitoJUnit.collector().assertLazily();
+
+        IMethods methods = mock(IMethods.class);
+        methods.simpleMethod();
+
+        verify(methods).simpleMethod();
+        collector.collectAndReport();
+    }
+
+    @Test(expected = MockitoAssertionError.class)
+    public void should_collect_verification_failures() {
+        VerificationCollector collector = MockitoJUnit.collector().assertLazily();
+
+        IMethods methods = mock(IMethods.class);
+
+        verify(methods).simpleMethod();
+        collector.collectAndReport();
+    }
+
+    @Test
+    public void should_collect_multiple_verification_failures() {
+        VerificationCollector collector = MockitoJUnit.collector().assertLazily();
+
+        IMethods methods = mock(IMethods.class);
+
+        verify(methods).simpleMethod();
+        verify(methods).byteReturningMethod();
+        try {
+            collector.collectAndReport();
+            fail();
+        } catch (MockitoAssertionError error) {
+            assertThat(error).hasMessageContaining("1. Wanted but not invoked:");
+            assertThat(error).hasMessageContaining("2. Wanted but not invoked:");
+        }
+    }
+
+    @Test
+    public void should_only_collect_failures_ignore_succesful_verifications() {
+        VerificationCollector collector = MockitoJUnit.collector().assertLazily();
+
+        IMethods methods = mock(IMethods.class);
+
+        verify(methods, never()).simpleMethod();
+        verify(methods).byteReturningMethod();
+
+        this.assertAtLeastOneFailure(collector);
+    }
+
+    @Test
+    public void should_continue_collecting_after_failing_verification() {
+        VerificationCollector collector = MockitoJUnit.collector().assertLazily();
+
+        IMethods methods = mock(IMethods.class);
+        methods.simpleMethod();
+
+        verify(methods).byteReturningMethod();
+        verify(methods).simpleMethod();
+
+        this.assertAtLeastOneFailure(collector);
+    }
+
+    private void assertAtLeastOneFailure(VerificationCollector collector) {
+        try {
+            collector.collectAndReport();
+            fail();
+        } catch (MockitoAssertionError error) {
+            assertThat(error).hasMessageContaining("1. Wanted but not invoked:");
+            assertThat(error.getMessage()).doesNotContain("2.");
+        }
+    }
+
+    @Test
+    public void should_invoke_collector_rule_after_test() {
+        JUnitCore runner = new JUnitCore();
+        Result result = runner.run(VerificationCollectorRuleInner.class);
+
+        assertThat(result.getFailureCount()).isEqualTo(1);
+        assertThat(result.getFailures().get(0).getMessage()).contains("1. Wanted but not invoked:");
+    }
+
+    // This class is picked up when running a test suite using an IDE. It fails on purpose.
+    public static class VerificationCollectorRuleInner {
+
+        @Rule
+        public VerificationCollector collector = MockitoJUnit.collector();
+
+        @Test
+        public void should_fail() {
+            IMethods methods = mock(IMethods.class);
+
+            verify(methods).simpleMethod();
+        }
+
+        @Test
+        public void should_not_fail() {
+            IMethods methods = mock(IMethods.class);
+            methods.simpleMethod();
+
+            verify(methods).simpleMethod();
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/DeepStubbingWithJUnitRunnerTest.java b/src/test/java/org/mockitousage/junitrunner/DeepStubbingWithJUnitRunnerTest.java
new file mode 100644
index 0000000..6674db5
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/DeepStubbingWithJUnitRunnerTest.java
@@ -0,0 +1,41 @@
+package org.mockitousage.junitrunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DeepStubbingWithJUnitRunnerTest {
+
+    private final SomeClass someClass = new SomeClass();
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Root root;
+
+    @Test
+    public void deep_stubs_dont_trigger_unnecessary_stubbing_exception() {
+        //when
+        someClass.someMethod(root);
+
+        //then unnecessary stubbing exception is not thrown
+    }
+
+    public static class SomeClass {
+        void someMethod(Root root) {
+            root.getFoo().getBar();
+        }
+    }
+
+    interface Root {
+        Foo getFoo();
+    }
+
+    interface Foo {
+        Bar getBar();
+    }
+
+    interface Bar {
+
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/Filters.java b/src/test/java/org/mockitousage/junitrunner/Filters.java
new file mode 100644
index 0000000..099acb7
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/Filters.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.junitrunner;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+
+public class Filters {
+    public static Filter methodNameContains(final String substring) {
+        return new Filter() {
+            @Override
+            public boolean shouldRun(Description description) {
+                return description.getDisplayName().contains(substring);
+            }
+
+            @Override
+            public String describe() {
+                return null;
+            }
+        };
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/JUnit45RunnerTest.java b/src/test/java/org/mockitousage/junitrunner/JUnit45RunnerTest.java
new file mode 100644
index 0000000..fe942e6
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/JUnit45RunnerTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.junitrunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.List;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.verify;
+import static org.mockitousage.junitrunner.Filters.methodNameContains;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JUnit45RunnerTest {
+
+    @InjectMocks private ListDependent listDependent = new ListDependent();
+    @Mock private List<String> list;
+
+    @Test
+    public void shouldInitMocksUsingRunner() {
+        list.add("test");
+        verify(list).add("test");
+    }
+
+    @Test
+    public void shouldInjectMocksUsingRunner() {
+        assertNotNull(list);
+        assertSame(list, listDependent.getList());
+    }
+
+    @Test
+    public void shouldFilterTestMethodsCorrectly() throws Exception{
+        MockitoJUnitRunner runner = new MockitoJUnitRunner(this.getClass());
+
+        runner.filter(methodNameContains("shouldInitMocksUsingRunner"));
+
+        assertEquals(1, runner.testCount());
+    }
+
+    class ListDependent {
+        private List<?> list;
+
+        public List<?> getList() {
+            return list;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/ModellingVerboseMockitoTest.java b/src/test/java/org/mockitousage/junitrunner/ModellingVerboseMockitoTest.java
new file mode 100644
index 0000000..9548917
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/ModellingVerboseMockitoTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.junitrunner;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+//@RunWith(ConsoleSpammingMockitoJUnitRunner.class)
+@RunWith(MockitoJUnitRunner.class)
+@Ignore
+public class ModellingVerboseMockitoTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Before
+    public void cleanStackTraces() {
+        super.makeStackTracesClean();
+    }
+
+    @Test
+    public void shouldLogUnusedStubbingWarningWhenTestFails() throws Exception {
+        when(mock.simpleMethod(1)).thenReturn("foo");
+        when(mock.otherMethod()).thenReturn("foo");
+        when(mock.booleanObjectReturningMethod()).thenReturn(false);
+
+        //TODO: stubbed with those args here -> stubbed with certain args here
+        String ret = mock.simpleMethod(2);
+
+        assertEquals("foo", ret);
+        //TODO: should show message from actual failure not at the bottom but at least below 'the actual failure is ...'
+    }
+
+    @Test
+    public void shouldNotLogAnythingWhenNoWarnings() throws Exception {
+        //stub
+        when(mock.simpleMethod()).thenReturn("foo");
+        //use stub:
+        mock.simpleMethod();
+        //verify:
+        verify(mock).simpleMethod();
+        //should be no warnings:
+        fail();
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/SilentRunnerTest.java b/src/test/java/org/mockitousage/junitrunner/SilentRunnerTest.java
new file mode 100644
index 0000000..6573d0e
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/SilentRunnerTest.java
@@ -0,0 +1,128 @@
+package org.mockitousage.junitrunner;
+
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.JUnitResultAssert;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class SilentRunnerTest extends TestBase {
+
+    JUnitCore runner = new JUnitCore();
+
+    @Test public void passing_test() {
+        //when
+        Result result = runner.run(
+                SomeFeature.class
+        );
+        //then
+        JUnitResultAssert.assertThat(result).isSuccessful();
+    }
+
+    @Test public void failing_test() {
+        //when
+        Result result = runner.run(
+                SomeFailingFeature.class
+        );
+        //then
+        JUnitResultAssert.assertThat(result).fails(1, TooLittleActualInvocations.class);
+    }
+
+    @Test public void failing_test_in_constructor() {
+        //when
+        Result result = runner.run(
+                FailsInConstructor.class
+        );
+        //then
+        JUnitResultAssert.assertThat(result).fails(1, IllegalArgumentException.class);
+    }
+
+    @Test public void validates_framework_usage() {
+        //when
+        Result result = runner.run(
+                UsesFrameworkIncorrectly.class
+        );
+        //then
+        JUnitResultAssert.assertThat(result).fails(1, "unfinished_stubbing_test_method", UnfinishedStubbingException.class);
+    }
+
+    @Test
+    public void ignores_unused_stubs() {
+        JUnitCore runner = new JUnitCore();
+        //when
+        Result result = runner.run(HasUnnecessaryStubs.class);
+        //then
+        JUnitResultAssert.assertThat(result).isSuccessful();
+    }
+
+    @RunWith(MockitoJUnitRunner.Silent.class)
+    public static class SomeFeature {
+        @Mock List<String> list;
+        @Test public void some_behavior() {
+            when(list.get(0)).thenReturn("0");
+            assertEquals("0", list.get(0));
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.Silent.class)
+    public static class SomeFailingFeature {
+        @Mock List<String> list;
+        @Test public void some_failing_behavior() {
+            list.clear();
+            verify(list, times(2)).clear();
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.Silent.class)
+    public static class FailsInConstructor {
+        {
+            if (System.currentTimeMillis() > 0) {
+                throw new IllegalArgumentException("Boo!");
+            }
+        }
+        @Mock List<String> list;
+        @Test public void some_behavior() {}
+    }
+
+    @RunWith(MockitoJUnitRunner.Silent.class)
+    public static class UsesFrameworkIncorrectly {
+        @Mock List<?> list;
+        @Test public void unfinished_stubbing_test_method() {
+            when(list.get(0)); //unfinished stubbing
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.Silent.class)
+    /**
+     * The test class itself is passing but it has some unnecessary stubs
+     */
+    public static class HasUnnecessaryStubs {
+        IMethods mock1 = when(mock(IMethods.class).simpleMethod(1)).thenReturn("1").getMock();
+        IMethods mock2 = when(mock(IMethods.class).simpleMethod(2)).thenReturn("2").getMock();
+        IMethods mock3 = when(mock(IMethods.class).simpleMethod(3)).thenReturn("3").getMock();
+
+        @Test
+        public void usesStub() {
+            assertEquals("1", mock1.simpleMethod(1));
+        }
+
+        @Test
+        public void usesStubWithDifferentArg() {
+            assertEquals(null, mock2.simpleMethod(200));
+            assertEquals(null, mock3.simpleMethod(300));
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/StrictRunnerTest.java b/src/test/java/org/mockitousage/junitrunner/StrictRunnerTest.java
new file mode 100644
index 0000000..de1c68e
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/StrictRunnerTest.java
@@ -0,0 +1,178 @@
+package org.mockitousage.junitrunner;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.JUnitResultAssert;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+public class StrictRunnerTest extends TestBase {
+
+    JUnitCore runner = new JUnitCore();
+
+    @Test public void succeeds_when_all_stubs_were_used() {
+        //when
+        Result result = runner.run(
+                StubbingInConstructorUsed.class,
+                StubbingInBeforeUsed.class,
+                StubbingInTestUsed.class
+        );
+        //then
+        JUnitResultAssert.assertThat(result).isSuccessful();
+    }
+
+    @Test public void fails_when_stubs_were_not_used() {
+        Class[] tests = {StubbingInConstructorUnused.class,
+                StubbingInBeforeUnused.class,
+                StubbingInTestUnused.class};
+
+        //when
+        Result result = runner.run(tests);
+
+        //then
+        JUnitResultAssert.assertThat(result).fails(3, UnnecessaryStubbingException.class);
+    }
+
+    @Test public void does_not_report_unused_stubs_when_different_failure_is_present() {
+        //when
+        Result result = runner.run(WithUnrelatedAssertionFailure.class);
+
+        //then
+        JUnitResultAssert.assertThat(result).fails(1, MyAssertionError.class);
+    }
+
+    @Test public void runner_can_coexist_with_rule() {
+        //I don't believe that this scenario is useful
+        //I only wish that Mockito does not break awkwardly when both: runner & rule is used
+
+        //when
+        Result result = runner.run(RunnerAndRule.class);
+
+        //then
+        JUnitResultAssert.assertThat(result).fails(1, UnnecessaryStubbingException.class);
+    }
+
+    @Test public void runner_in_multi_threaded_tests() {
+        //when
+        Result result = runner.run(StubUsedFromDifferentThread.class);
+
+        //then
+        JUnitResultAssert.assertThat(result).isSuccessful();
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class StubbingInConstructorUsed extends StubbingInConstructorUnused {
+        @Test public void test() {
+            assertEquals("1", mock.simpleMethod(1));
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.Strict.class) //using Strict to make sure it does the right thing
+    public static class StubbingInConstructorUnused {
+        IMethods mock = when(mock(IMethods.class).simpleMethod(1)).thenReturn("1").getMock();
+        @Test public void dummy() {}
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class StubbingInBeforeUsed extends StubbingInBeforeUnused {
+        @Test public void test() {
+            assertEquals("1", mock.simpleMethod(1));
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class StubbingInBeforeUnused {
+        @Mock IMethods mock;
+        @Before public void before() {
+            when(mock.simpleMethod(1)).thenReturn("1");
+        }
+        @Test public void dummy() {}
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class StubbingInTestUsed {
+        @Test public void test() {
+            IMethods mock = mock(IMethods.class);
+            when(mock.simpleMethod(1)).thenReturn("1");
+            assertEquals("1", mock.simpleMethod(1));
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class StubbingInTestUnused {
+        @Test public void test() {
+            IMethods mock = mock(IMethods.class);
+            when(mock.simpleMethod(1)).thenReturn("1");
+            mock.simpleMethod(2); //different arg
+        }
+    }
+
+    private static class MyAssertionError extends AssertionError {}
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class WithUnrelatedAssertionFailure {
+
+        IMethods mock = mock(IMethods.class);
+        IMethods mock2 = mock(IMethods.class);
+
+        @Before public void before() {
+            when(mock2.simpleMethod("unused stubbing")).thenReturn("");
+        }
+
+        @Test public void passing_test() {
+            when(mock.simpleMethod(1)).thenReturn("1");
+            assertEquals("1", mock.simpleMethod(1));
+        }
+
+        @Test public void failing_test() {
+            throw new MyAssertionError();
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class RunnerAndRule {
+
+        public @Rule MockitoRule rule = MockitoJUnit.rule();
+        IMethods mock = mock(IMethods.class);
+
+        @Test public void passing_test() {
+            when(mock.simpleMethod(1)).thenReturn("1");
+            mock.simpleMethod(2);
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class StubUsedFromDifferentThread {
+
+        IMethods mock = mock(IMethods.class);
+
+        @Test public void passing_test() throws Exception {
+            //stubbing is done in main thread:
+            when(mock.simpleMethod(1)).thenReturn("1");
+
+            //stubbing is used in a different thread
+            //stubbing should not be reported as unused by the runner
+            Thread t = new Thread() {
+                public void run() {
+                    mock.simpleMethod(1);
+                }
+            };
+            t.start();
+            t.join();
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/StrictStubsRunnerTest.java b/src/test/java/org/mockitousage/junitrunner/StrictStubsRunnerTest.java
new file mode 100644
index 0000000..94d45ca
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/StrictStubsRunnerTest.java
@@ -0,0 +1,68 @@
+package org.mockitousage.junitrunner;
+
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.PotentialStubbingProblem;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.JUnitResultAssert;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+public class StrictStubsRunnerTest extends TestBase {
+
+    JUnitCore runner = new JUnitCore();
+
+    @Test public void detects_unnecessary_stubbings() {
+        //when
+        Result result = runner.run(UnnecessaryStubbing.class);
+        //then
+        JUnitResultAssert.assertThat(result)
+                .fails(1, UnnecessaryStubbingException.class)
+                .succeeds(2);
+    }
+
+    @Test public void fails_fast_on_argument_mismatch() {
+        //when
+        Result result = runner.run(StubbingArgMismatch.class);
+        //then
+        JUnitResultAssert.assertThat(result)
+                .succeeds(2)
+                .fails(1, PotentialStubbingProblem.class);
+    }
+
+    @RunWith(MockitoJUnitRunner.StrictStubs.class)
+    public static class UnnecessaryStubbing {
+        @Mock IMethods mock;
+        @Test public void unused_stubbing_1() {
+            when(mock.simpleMethod()).thenReturn("");
+        }
+        @Test public void unused_stubbing_2() {
+            when(mock.simpleMethod()).thenReturn("");
+        }
+        @Test public void correct_stubbing() {
+            when(mock.simpleMethod()).thenReturn("");
+            mock.simpleMethod();
+        }
+    }
+
+    @RunWith(MockitoJUnitRunner.StrictStubs.class)
+    public static class StubbingArgMismatch {
+        @Mock IMethods mock;
+        @Test public void passing1() {}
+        @Test public void passing2() {
+            when(mock.simpleMethod()).thenReturn("");
+            mock.simpleMethod();
+        }
+        @Test public void argument_mismatch() {
+            when(mock.simpleMethod(10)).thenReturn("");
+            mock.simpleMethod(20);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/StubbingWarningsJUnitRunnerTest.java b/src/test/java/org/mockitousage/junitrunner/StubbingWarningsJUnitRunnerTest.java
new file mode 100644
index 0000000..d7c425f
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/StubbingWarningsJUnitRunnerTest.java
@@ -0,0 +1,122 @@
+package org.mockitousage.junitrunner;
+
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockito.junit.TestableJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockitoutil.JUnitResultAssert.assertThat;
+
+public class StubbingWarningsJUnitRunnerTest extends TestBase {
+
+    JUnitCore runner = new JUnitCore();
+    SimpleMockitoLogger logger = TestableJUnitRunner.refreshedLogger();
+
+    @Test public void no_arg_mismatch_warnings() {
+        //when
+        runner.run(PassingArgMismatch.class, FailingWithMatchingArgs.class, MismatchButStubAlreadyUsed.class);
+
+        //then
+        assertEquals("", filterLineNo(logger.getLoggedInfo()));
+    }
+
+    @Test public void shows_arg_mismatch_warnings_when_test_fails() {
+        //when
+        runner.run(FailingWithArgMismatch.class);
+
+        //then
+        assertEquals("[MockitoHint] FailingWithArgMismatch.test (see javadoc for MockitoHint):\n" +
+                "[MockitoHint] 1. Unused... -> at org.mockitousage.junitrunner.StubbingWarningsJUnitRunnerTest$FailingWithArgMismatch.test(StubbingWarningsJUnitRunnerTest.java:0)\n" +
+                "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrunner.StubbingWarningsJUnitRunnerTest$FailingWithArgMismatch.test(StubbingWarningsJUnitRunnerTest.java:0)\n", filterLineNo(logger.getLoggedInfo()));
+    }
+
+    @Test public void shows_arg_mismatch_warnings_only_for_mismatches() {
+        //when
+        runner.run(FailingWithSomeStubMismatches.class);
+
+        //then
+        assertEquals("[MockitoHint] FailingWithSomeStubMismatches.test (see javadoc for MockitoHint):\n" +
+                "[MockitoHint] 1. Unused... -> at org.mockitousage.junitrunner.StubbingWarningsJUnitRunnerTest$FailingWithSomeStubMismatches.test(StubbingWarningsJUnitRunnerTest.java:0)\n" +
+                "[MockitoHint]  ...args ok? -> at org.mockitousage.junitrunner.StubbingWarningsJUnitRunnerTest$FailingWithSomeStubMismatches.test(StubbingWarningsJUnitRunnerTest.java:0)\n", filterLineNo(logger.getLoggedInfo()));
+    }
+
+    @Test public void validates_mockito_usage() {
+        //when
+        Result result = runner.run(InvalidMockitoUsage.class);
+
+        //then
+        assertThat(result).fails(1, UnfinishedStubbingException.class);
+    }
+
+    @RunWith(TestableJUnitRunner.class)
+    public static class PassingArgMismatch {
+        IMethods mock = mock(IMethods.class);
+        @Test public void test() throws Exception {
+            when(mock.simpleMethod(1)).thenReturn("1");
+            mock.simpleMethod(2);
+        }
+    }
+
+    @RunWith(TestableJUnitRunner.class)
+    public static class FailingWithArgMismatch {
+        @Mock IMethods mock;
+        @Test public void test() throws Exception {
+            when(mock.simpleMethod(1)).thenReturn("1");
+            mock.simpleMethod(2);
+            throw new RuntimeException("x");
+        }
+    }
+
+    @RunWith(TestableJUnitRunner.class)
+    public static class FailingWithMatchingArgs {
+        @Mock IMethods mock;
+        @Test public void test() throws Exception {
+            when(mock.simpleMethod(1)).thenReturn("1");
+            mock.simpleMethod(1);
+            throw new RuntimeException("x");
+        }
+    }
+
+    @RunWith(TestableJUnitRunner.class)
+    public static class FailingWithSomeStubMismatches {
+        @Mock IMethods mock;
+        @Test public void test() throws Exception {
+            when(mock.simpleMethod(1)).thenReturn("1"); // <- used
+            when(mock.simpleMethod(2)).thenReturn("2"); // <- unused
+
+            mock.simpleMethod(1); // <- not reported
+            mock.simpleMethod(3); // <- reported
+
+            throw new RuntimeException("x");
+        }
+    }
+
+    @RunWith(TestableJUnitRunner.class)
+    public static class MismatchButStubAlreadyUsed {
+        @Mock IMethods mock;
+        @Test public void test() throws Exception {
+            when(mock.simpleMethod(1)).thenReturn("1");
+            mock.simpleMethod(1); // <-- used
+            mock.simpleMethod(2); // <-- arg mismatch, but the stub was already used
+
+            throw new RuntimeException("x");
+        }
+    }
+
+    @RunWith(TestableJUnitRunner.class)
+    public static class InvalidMockitoUsage {
+        @Mock IMethods mock;
+        @Test public void test() throws Exception {
+            when(mock.simpleMethod()); // <-- unfinished stubbing
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/UnusedStubsExceptionMessageTest.java b/src/test/java/org/mockitousage/junitrunner/UnusedStubsExceptionMessageTest.java
new file mode 100644
index 0000000..15c0cf5
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/UnusedStubsExceptionMessageTest.java
@@ -0,0 +1,55 @@
+package org.mockitousage.junitrunner;
+
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.Failure;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class UnusedStubsExceptionMessageTest extends TestBase {
+
+    //Moving the code around this class is tricky and may cause the test to fail
+    //We're asserting on full exception message which contains line numbers
+    //Let's leave it for now, updating the test is cheap and if it turns out hindrance we can make the assertion smarter.
+    @RunWith(MockitoJUnitRunner.class)
+    public static class HasUnnecessaryStubs {
+        IMethods mock1 = when(mock(IMethods.class).simpleMethod(1)).thenReturn("1").getMock();
+        IMethods mock2 = when(mock(IMethods.class).simpleMethod(2)).thenReturn("2").getMock();
+        IMethods mock3 = when(mock(IMethods.class).simpleMethod(3)).thenReturn("3").getMock();
+
+        @Test
+        public void usesStub() {
+            assertEquals("1", mock1.simpleMethod(1));
+        }
+
+        @Test
+        public void usesStubWithDifferentArg() {
+            assertEquals(null, mock2.simpleMethod(200));
+            assertEquals(null, mock3.simpleMethod(300));
+        }
+    }
+
+    @Test
+    public void lists_all_unused_stubs_cleanly() {
+        JUnitCore runner = new JUnitCore();
+        //when
+        Result result = runner.run(HasUnnecessaryStubs.class);
+        //then
+        Failure failure = result.getFailures().get(0);
+        assertEquals("\n" +
+                        "Unnecessary stubbings detected in test class: HasUnnecessaryStubs\n" +
+                        "Clean & maintainable test code requires zero unnecessary code.\n" +
+                        "Following stubbings are unnecessary (click to navigate to relevant line of code):\n" +
+                        "  1. -> at org.mockitousage.junitrunner.UnusedStubsExceptionMessageTest$HasUnnecessaryStubs.<init>(UnusedStubsExceptionMessageTest.java:0)\n" +
+                        "  2. -> at org.mockitousage.junitrunner.UnusedStubsExceptionMessageTest$HasUnnecessaryStubs.<init>(UnusedStubsExceptionMessageTest.java:0)\n" +
+                        "Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.",
+                filterLineNo(failure.getException().getMessage()));
+    }
+}
diff --git a/src/test/java/org/mockitousage/junitrunner/VerboseMockitoRunnerTest.java b/src/test/java/org/mockitousage/junitrunner/VerboseMockitoRunnerTest.java
new file mode 100644
index 0000000..8e08a1e
--- /dev/null
+++ b/src/test/java/org/mockitousage/junitrunner/VerboseMockitoRunnerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.junitrunner;
+
+import junit.framework.TestCase;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
+import org.mockito.runners.VerboseMockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Mockito.*;
+
+//@RunWith(ConsoleSpammingMockitoJUnitRunner.class)
+@RunWith(VerboseMockitoJUnitRunner.class)
+//TODO
+public class VerboseMockitoRunnerTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    public static class NoWarnings {
+
+        @Test
+        @Ignore
+        public void test() {
+            IMethods mock = mock(IMethods.class);
+            mock.simpleMethod(1);
+            mock.otherMethod();
+
+            verify(mock).simpleMethod(1);
+            throw new RuntimeException("boo");
+        }
+    }
+
+    public static class ContainsWarnings extends TestCase {
+
+        public ContainsWarnings() {
+            super("test");
+        }
+
+        public void testIgnored() {}
+
+        public void _test() {
+            IMethods mock = mock(IMethods.class);
+
+            //some stubbing
+            when(mock.simpleMethod(1)).thenReturn("foo");
+            when(mock.otherMethod()).thenReturn("foo");
+            when(mock.booleanObjectReturningMethod()).thenReturn(false);
+
+            //stub called with different args:
+            String ret = mock.simpleMethod(2);
+
+            //assertion fails due to stub called with different args
+            assertEquals("foo", ret);
+        }
+    }
+
+    public void cleanStackTraces() {
+        makeStackTracesClean();
+    }
+
+    @Test
+    @Ignore
+    public void shouldContainWarnings() throws Exception {
+        //when
+        Result result = new JUnitCore().run(new ContainsWarnings());
+        //then
+        assertEquals(1, result.getFailures().size());
+        Throwable exception = result.getFailures().get(0).getException();
+        assertTrue(exception instanceof ExceptionIncludingMockitoWarnings);
+    }
+
+    @Test
+    @Ignore
+    public void shouldNotContainWarnings() throws Exception {
+        Result result = new JUnitCore().run(NoWarnings.class);
+        assertEquals(1, result.getFailures().size());
+        assertEquals("boo", result.getFailures().get(0).getException().getMessage());
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/AnyXMatchersAcceptNullsTest.java b/src/test/java/org/mockitousage/matchers/AnyXMatchersAcceptNullsTest.java
new file mode 100644
index 0000000..5c0a17f
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/AnyXMatchersAcceptNullsTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.matchers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("unchecked")
+public class AnyXMatchersAcceptNullsTest extends TestBase {
+
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = Mockito.mock(IMethods.class);
+    }
+
+    @Test
+    public void shouldAcceptNullsInAnyMatcher() {
+        when(mock.oneArg((Object) any())).thenReturn("matched");
+
+        assertEquals(null, mock.forObject(null));
+    }
+
+    @Test
+    public void shouldAcceptNullsInAnyObjectMatcher() {
+        when(mock.oneArg((Object) anyObject())).thenReturn("matched");
+
+        assertEquals(null, mock.forObject(null));
+    }
+
+    @Test
+    public void shouldNotAcceptNullInAnyXMatchers() {
+        when(mock.oneArg(anyString())).thenReturn("0");
+        when(mock.forList(anyListOf(String.class))).thenReturn("1");
+        when(mock.forMap(anyMapOf(String.class, String.class))).thenReturn("2");
+        when(mock.forCollection(anyCollectionOf(String.class))).thenReturn("3");
+        when(mock.forSet(anySetOf(String.class))).thenReturn("4");
+
+        assertEquals(null, mock.oneArg((Object) null));
+        assertEquals(null, mock.oneArg((String) null));
+        assertEquals(null, mock.forList(null));
+        assertEquals(null, mock.forMap(null));
+        assertEquals(null, mock.forCollection(null));
+        assertEquals(null, mock.forSet(null));
+    }
+
+    @Test
+    public void shouldNotAcceptNullInAllAnyPrimitiveWrapperMatchers() {
+        when(mock.forInteger(anyInt())).thenReturn("0");
+        when(mock.forCharacter(anyChar())).thenReturn("1");
+        when(mock.forShort(anyShort())).thenReturn("2");
+        when(mock.forByte(anyByte())).thenReturn("3");
+        when(mock.forBoolean(anyBoolean())).thenReturn("4");
+        when(mock.forLong(anyLong())).thenReturn("5");
+        when(mock.forFloat(anyFloat())).thenReturn("6");
+        when(mock.forDouble(anyDouble())).thenReturn("7");
+
+        assertEquals(null, mock.forInteger(null));
+        assertEquals(null, mock.forCharacter(null));
+        assertEquals(null, mock.forShort(null));
+        assertEquals(null, mock.forByte(null));
+        assertEquals(null, mock.forBoolean(null));
+        assertEquals(null, mock.forLong(null));
+        assertEquals(null, mock.forFloat(null));
+        assertEquals(null, mock.forDouble(null));
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/CapturingArgumentsTest.java b/src/test/java/org/mockitousage/matchers/CapturingArgumentsTest.java
new file mode 100644
index 0000000..ccc489c
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/CapturingArgumentsTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class CapturingArgumentsTest extends TestBase {
+
+    class Person {
+
+        private final Integer age;
+
+        public Person(Integer age) {
+            this.age = age;
+        }
+
+        public int getAge() {
+            return age;
+        }
+    }
+
+    class BulkEmailService {
+
+        private EmailService service;
+
+        public BulkEmailService(EmailService service) {
+            this.service = service;
+        }
+
+        public void email(Integer ... personId) {
+            for (Integer i : personId) {
+                Person person = new Person(i);
+                service.sendEmailTo(person);
+            }
+        }
+    }
+
+    interface EmailService {
+        boolean sendEmailTo(Person person);
+    }
+
+    EmailService emailService = mock(EmailService.class);
+    BulkEmailService bulkEmailService = new BulkEmailService(emailService);
+    IMethods mock = mock(IMethods.class);
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void should_allow_assertions_on_captured_argument() {
+        //given
+        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+
+        //when
+        bulkEmailService.email(12);
+
+        //then
+        verify(emailService).sendEmailTo(argument.capture());
+        assertEquals(12, argument.getValue().getAge());
+    }
+
+    @Test
+    public void should_allow_assertions_on_all_captured_arguments() {
+        //given
+        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+
+        //when
+        bulkEmailService.email(11, 12);
+
+        //then
+        verify(emailService, times(2)).sendEmailTo(argument.capture());
+        assertEquals(11, argument.getAllValues().get(0).getAge());
+        assertEquals(12, argument.getAllValues().get(1).getAge());
+    }
+
+    @Test
+    public void should_allow_assertions_on_last_argument() {
+        //given
+        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+
+        //when
+        bulkEmailService.email(11, 12, 13);
+
+        //then
+        verify(emailService, times(3)).sendEmailTo(argument.capture());
+        assertEquals(13, argument.getValue().getAge());
+    }
+
+    @Test
+    public void should_print_captor_matcher() {
+        //given
+        ArgumentCaptor<Person> person = ArgumentCaptor.forClass(Person.class);
+
+        try {
+            //when
+            verify(emailService).sendEmailTo(person.capture());
+            fail();
+        } catch(WantedButNotInvoked e) {
+            //then
+            assertThat(e).hasMessageContaining("<Capturing argument>");
+        }
+    }
+
+    @Test
+    public void should_allow_assertions_on_captured_null() {
+        //given
+        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+
+        //when
+        emailService.sendEmailTo(null);
+
+        //then
+        verify(emailService).sendEmailTo(argument.capture());
+        assertEquals(null, argument.getValue());
+    }
+
+    @Test
+    public void should_allow_construction_of_captor_for_parameterized_type_in_a_convenient_way()  {
+        //the test passes if this expression compiles
+        @SuppressWarnings("unchecked")
+        ArgumentCaptor<List<Person>> argument = ArgumentCaptor.forClass(List.class);
+        assertNotNull(argument);
+    }
+
+    @Test
+    public void should_allow_construction_of_captor_for_a_more_specific_type()  {
+        //the test passes if this expression compiles
+        ArgumentCaptor<List<?>> argument = ArgumentCaptor.forClass(ArrayList.class);
+        assertNotNull(argument);
+    }
+
+    @Test
+    public void should_allow_capturing_for_stubbing() {
+        //given
+        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+        when(emailService.sendEmailTo(argument.capture())).thenReturn(false);
+
+        //when
+        emailService.sendEmailTo(new Person(10));
+
+        //then
+        assertEquals(10, argument.getValue().getAge());
+    }
+
+    @Test
+    public void should_capture_when_stubbing_only_when_entire_invocation_matches() {
+        //given
+        ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
+        when(mock.simpleMethod(argument.capture(), eq(2))).thenReturn("blah");
+
+        //when
+        mock.simpleMethod("foo", 200);
+        mock.simpleMethod("bar", 2);
+
+        //then
+        Assertions.assertThat(argument.getAllValues()).containsOnly("bar");
+    }
+
+    @Test
+    public void should_say_something_smart_when_misused() {
+        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+        try {
+            argument.getValue();
+            fail();
+        } catch (MockitoException expected) { }
+    }
+
+    @Test
+    public void should_capture_when_full_arg_list_matches() throws Exception {
+        //given
+        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+
+        //when
+        mock.simpleMethod("foo", 1);
+        mock.simpleMethod("bar", 2);
+
+        //then
+        verify(mock).simpleMethod(captor.capture(), eq(1));
+        assertEquals(1, captor.getAllValues().size());
+        assertEquals("foo", captor.getValue());
+    }
+
+    @Test
+    public void should_capture_int_by_creating_captor_with_primitive_wrapper() {
+        //given
+        ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+        //when
+        mock.intArgumentMethod(10);
+
+        //then
+        verify(mock).intArgumentMethod(argument.capture());
+        assertEquals(10, (int) argument.getValue());
+    }
+
+    @Test
+    public void should_capture_int_by_creating_captor_with_primitive() throws Exception {
+        //given
+        ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(int.class);
+
+        //when
+        mock.intArgumentMethod(10);
+
+        //then
+        verify(mock).intArgumentMethod(argument.capture());
+        assertEquals(10, (int) argument.getValue());
+    }
+
+    @Test
+    public void should_capture_byte_vararg_by_creating_captor_with_primitive() throws Exception {
+        // given
+        ArgumentCaptor<Byte> argumentCaptor = ArgumentCaptor.forClass(byte.class);
+
+        // when
+        mock.varargsbyte((byte) 1, (byte) 2);
+
+        // then
+        verify(mock).varargsbyte(argumentCaptor.capture());
+        assertEquals((byte) 2, (byte) argumentCaptor.getValue());
+        Assertions.assertThat(argumentCaptor.getAllValues()).containsExactly((byte) 1, (byte) 2);
+    }
+
+    @Test
+    public void should_capture_byte_vararg_by_creating_captor_with_primitive_wrapper() throws Exception {
+        // given
+        ArgumentCaptor<Byte> argumentCaptor = ArgumentCaptor.forClass(Byte.class);
+
+        // when
+        mock.varargsbyte((byte) 1, (byte) 2);
+
+        // then
+        verify(mock).varargsbyte(argumentCaptor.capture());
+        assertEquals((byte) 2, (byte) argumentCaptor.getValue());
+        Assertions.assertThat(argumentCaptor.getAllValues()).containsExactly((byte) 1, (byte) 2);
+    }
+
+    @Test
+    public void should_capture_vararg() throws Exception {
+        // given
+        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
+
+        // when
+        mock.mixedVarargs(42, "a", "b", "c");
+
+        // then
+        verify(mock).mixedVarargs(any(), argumentCaptor.capture());
+        Assertions.assertThat(argumentCaptor.getAllValues()).containsExactly("a", "b", "c");
+    }
+
+    @Test
+    public void should_capture_all_vararg() throws Exception {
+        // given
+        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
+
+        // when
+        mock.mixedVarargs(42, "a", "b", "c");
+        mock.mixedVarargs(42, "again ?!");
+
+        // then
+        verify(mock, times(2)).mixedVarargs(any(), argumentCaptor.capture());
+
+        Assertions.assertThat(argumentCaptor.getAllValues()).containsExactly("a", "b", "c", "again ?!");
+    }
+
+    @Test
+    public void should_capture_one_arg_even_when_using_vararg_captor_on_nonvararg_method() throws Exception {
+        // given
+        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
+
+        // when
+        mock.simpleMethod("a", 2);
+
+        // then
+        verify(mock).simpleMethod(argumentCaptor.capture(), eq(2));
+        Assertions.assertThat(argumentCaptor.getAllValues()).containsExactly("a");
+    }
+
+    @Test
+    public void captures_correctly_when_captor_used_multiple_times() throws Exception {
+        // given
+        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
+
+        // when
+        mock.mixedVarargs(42, "a", "b", "c");
+
+        // then
+        // this is only for backwards compatibility. It does not make sense in real to do so.
+        verify(mock).mixedVarargs(any(), argumentCaptor.capture(), argumentCaptor.capture(), argumentCaptor.capture());
+        Assertions.assertThat(argumentCaptor.getAllValues()).containsExactly("a", "b", "c");
+    }
+
+    @Test
+    public void captures_correctly_when_captor_used_on_pure_vararg_method() throws Exception {
+        // given
+        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
+
+        // when
+        mock.varargs(42, "capturedValue");
+
+        // then
+        verify(mock).varargs(eq(42), argumentCaptor.capture());
+        Assertions.assertThat(argumentCaptor.getValue()).contains("capturedValue");
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/CustomMatcherDoesYieldCCETest.java b/src/test/java/org/mockitousage/matchers/CustomMatcherDoesYieldCCETest.java
new file mode 100644
index 0000000..eb9e5af
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/CustomMatcherDoesYieldCCETest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.matchers;
+
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.verify;
+
+public class CustomMatcherDoesYieldCCETest extends TestBase {
+
+    @Mock
+    private IMethods mock;
+
+    @Test
+    public void shouldNotThrowCCE() {
+        mock.simpleMethod(new Object());
+
+        try {
+            // calling overloaded method so that matcher will be called with
+            // different type
+            verify(mock).simpleMethod(argThat(isStringWithTextFoo()));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+        }
+    }
+
+    private ArgumentMatcher<String> isStringWithTextFoo() {
+        return new ArgumentMatcher<String>() {
+            public boolean matches(String argument) {
+                // casting that should not be thrown:
+                String str = (String) argument;
+                return str.equals("foo");
+            }
+        };
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/CustomMatchersTest.java b/src/test/java/org/mockitousage/matchers/CustomMatchersTest.java
new file mode 100644
index 0000000..6755b6e
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/CustomMatchersTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mockito;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class CustomMatchersTest extends TestBase {
+
+    private final class ContainsFoo implements ArgumentMatcher<String> {
+        public boolean matches(String arg) {
+            return arg.contains("foo");
+        }
+    }
+
+    private final class IsAnyBoolean implements ArgumentMatcher<Boolean> {
+        public boolean matches(Boolean arg) {
+            return true;
+        }
+    }
+
+    private final class IsSorZ implements ArgumentMatcher<Character> {
+        public boolean matches(Character character) {
+            return character.equals('s') || character.equals('z');
+        }
+    }
+
+    private final class IsZeroOrOne<T extends Number> implements ArgumentMatcher<T> {
+        public boolean matches(T number) {
+            return number.intValue() == 0 || number.intValue() == 1;
+        }
+    }
+
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = Mockito.mock(IMethods.class);
+    }
+
+    @Test
+    public void shouldUseCustomBooleanMatcher() {
+        when(mock.oneArg(booleanThat(new IsAnyBoolean()))).thenReturn("foo");
+
+        assertEquals("foo", mock.oneArg(true));
+        assertEquals("foo", mock.oneArg(false));
+
+        assertEquals(null, mock.oneArg("x"));
+    }
+
+    @Test
+    public void shouldUseCustomCharMatcher() {
+        when(mock.oneArg(charThat(new IsSorZ()))).thenReturn("foo");
+
+        assertEquals("foo", mock.oneArg('s'));
+        assertEquals("foo", mock.oneArg('z'));
+        assertEquals(null, mock.oneArg('x'));
+    }
+
+    class Article {
+
+        private int pageNumber;
+        private String headline;
+
+        public Article(int pageNumber, String headline) {
+            super();
+            this.pageNumber = pageNumber;
+            this.headline = headline;
+        }
+
+        public int getPageNumber() {
+            return pageNumber;
+        }
+
+        public String getHeadline() {
+            return headline;
+        }
+    }
+
+    @Test
+    public void shouldUseCustomPrimitiveNumberMatchers() {
+        when(mock.oneArg(byteThat(new IsZeroOrOne<Byte>()))).thenReturn("byte");
+        when(mock.oneArg(shortThat(new IsZeroOrOne<Short>()))).thenReturn("short");
+        when(mock.oneArg(intThat(new IsZeroOrOne<Integer>()))).thenReturn("int");
+        when(mock.oneArg(longThat(new IsZeroOrOne<Long>()))).thenReturn("long");
+        when(mock.oneArg(floatThat(new IsZeroOrOne<Float>()))).thenReturn("float");
+        when(mock.oneArg(doubleThat(new IsZeroOrOne<Double>()))).thenReturn("double");
+
+        assertEquals("byte", mock.oneArg((byte) 0));
+        assertEquals("short", mock.oneArg((short) 1));
+        assertEquals("int", mock.oneArg(0));
+        assertEquals("long", mock.oneArg(1L));
+        assertEquals("float", mock.oneArg(0F));
+        assertEquals("double", mock.oneArg(1.0));
+
+        assertEquals(null, mock.oneArg(2));
+        assertEquals(null, mock.oneArg("foo"));
+    }
+
+    @Test
+    public void shouldUseCustomObjectMatcher() {
+        when(mock.oneArg(argThat(new ContainsFoo()))).thenReturn("foo");
+
+        assertEquals("foo", mock.oneArg("foo"));
+        assertEquals(null, mock.oneArg("bar"));
+    }
+
+    @Test
+    public void shouldCustomMatcherPrintDescriptionBasedOnName() {
+        mock.simpleMethod("foo");
+
+        try {
+            verify(mock).simpleMethod(containsTest());
+            fail();
+        } catch (AssertionError e) {
+            assertThat(e).hasMessageContaining("<String that contains xxx>");
+        }
+    }
+
+    private String containsTest() {
+        return argThat(new StringThatContainsXxx());
+    }
+
+    private final class StringThatContainsXxx implements ArgumentMatcher<String> {
+        public boolean matches(String arg) {
+            return arg.contains("xxx");
+        }
+    }
+
+    @Test
+    public void shouldAnonymousCustomMatcherPrintDefaultDescription() {
+        mock.simpleMethod("foo");
+
+        try {
+            verify(mock).simpleMethod((String) argThat(new ArgumentMatcher<Object>() {
+                public boolean matches(Object argument) {
+                    return false;
+                }}));
+            fail();
+        } catch (AssertionError e) {
+            assertThat(e)
+                .hasMessageContaining("<custom argument matcher>")
+                .hasMessageContaining("foo");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/GenericMatchersTest.java b/src/test/java/org/mockitousage/matchers/GenericMatchersTest.java
new file mode 100644
index 0000000..89387c3
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/GenericMatchersTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+import java.util.Date;
+import java.util.List;
+
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.when;
+
+public class GenericMatchersTest extends TestBase {
+
+    private interface Foo {
+        List<String> sort(List<String> otherList);
+        String convertDate(Date date);
+    }
+
+    @Mock Foo sorter;
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void shouldCompile() {
+        when(sorter.convertDate(new Date())).thenReturn("one");
+        when(sorter.convertDate((Date) anyObject())).thenReturn("two");
+
+        //following requires warning suppression but allows setting anyList()
+        when(sorter.sort(ArgumentMatchers.<String>anyList())).thenReturn(null);
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/HamcrestMatchersTest.java b/src/test/java/org/mockitousage/matchers/HamcrestMatchersTest.java
new file mode 100644
index 0000000..f12769d
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/HamcrestMatchersTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.hamcrest.MockitoHamcrest.*;
+
+public class HamcrestMatchersTest extends TestBase {
+
+    private final class ContainsX extends BaseMatcher<String> {
+        public boolean matches(Object o) {
+            return ((String) o).contains("X");
+        }
+
+        public void describeTo(Description d) {
+            d.appendText("contains 'X'");
+        }
+    }
+
+    @Mock
+    private IMethods mock;
+
+    @Test
+    public void stubs_with_hamcrest_matcher() {
+        when(mock.simpleMethod(argThat(new ContainsX()))).thenReturn("X");
+        assertNull(mock.simpleMethod("blah"));
+        assertEquals("X", mock.simpleMethod("blah X blah"));
+    }
+
+    @Test
+    public void verifies_with_hamcrest_matcher() {
+        mock.simpleMethod("blah");
+
+        try {
+            verify(mock).simpleMethod(argThat(new ContainsX()));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e).hasMessageContaining("contains 'X'");
+        }
+    }
+
+    private class IntMatcher extends BaseMatcher<Integer> {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
+    @Test
+    public void supports_primitive_matchers() {
+        when(mock.intArgumentReturningInt(argThat(new IntMatcher()))).thenReturn(5);
+        assertEquals(5, mock.intArgumentReturningInt(10));
+    }
+
+    @Test
+    public void supports_primitive_matchers_from_core_library() {
+        mock.oneArg(true);
+        mock.oneArg((byte) 1);
+        mock.oneArg(2);
+        mock.oneArg(3L);
+        mock.oneArg('4');
+        mock.oneArg(5.0D);
+        mock.oneArg(6.0F);
+
+        verify(mock).oneArg(booleanThat(is(true)));
+        verify(mock).oneArg(byteThat(is((byte) 1)));
+        verify(mock).oneArg(intThat(is(2)));
+        verify(mock).oneArg(longThat(is(3L)));
+        verify(mock).oneArg(charThat(is('4')));
+        verify(mock).oneArg(doubleThat(is(5.0D)));
+        verify(mock).oneArg(floatThat(is(6.0F)));
+    }
+
+    @SuppressWarnings("rawtypes")
+    private class NonGenericMatcher extends BaseMatcher {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
+    @Test
+    public void supports_non_generic_matchers() {
+        when(mock.intArgumentReturningInt(nonGenericMatcher())).thenReturn(5);
+        assertEquals(5, mock.intArgumentReturningInt(10));
+    }
+
+    @SuppressWarnings("unchecked")
+    private int nonGenericMatcher() {
+        argThat(new NonGenericMatcher());
+        return 0;
+    }
+
+    @Test
+    public void coexists_with_mockito_matcher() {
+        when(mock.simpleMethod(Mockito.argThat(new ArgumentMatcher<String>() {
+            public boolean matches(String argument) {
+                return true;
+            }
+        }))).thenReturn("x");
+
+        assertEquals("x", mock.simpleMethod("x"));
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/InvalidUseOfMatchersTest.java b/src/test/java/org/mockitousage/matchers/InvalidUseOfMatchersTest.java
new file mode 100644
index 0000000..a562f1f
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/InvalidUseOfMatchersTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.mockito.AdditionalMatchers;
+import org.mockito.Mockito;
+import org.mockito.StateMaster;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.Silent.class)
+public class InvalidUseOfMatchersTest {
+
+    private IMethods mock = Mockito.mock(IMethods.class);
+
+    @Test
+    public void should_detect_wrong_number_of_matchers_when_stubbing() {
+        when(mock.threeArgumentMethod(1, "2", "3")).thenReturn(null);
+        try {
+            when(mock.threeArgumentMethod(1, eq("2"), "3")).thenReturn(null);
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e.getMessage())
+                    .contains("3 matchers expected")
+                    .contains("1 recorded");
+        }
+    }
+
+    @Test
+    public void should_detect_stupid_use_of_matchers_when_verifying() {
+        mock.oneArg(true);
+        eq("that's the stupid way");
+        eq("of using matchers");
+        try {
+            Mockito.verify(mock).oneArg(true);
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e.getMessage())
+                    .contains("Misplaced or misused argument matcher detected here");
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void should_not_scream_on_correct_usage() throws Exception {
+        mock.simpleMethod(AdditionalMatchers.not(eq("asd")));
+        mock.simpleMethod(AdditionalMatchers.or(eq("jkl"), eq("asd")));
+    }
+
+    @Test
+    public void should_scream_when_no_matchers_inside_not() {
+        try {
+            mock.simpleMethod(AdditionalMatchers.not("jkl"));
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e.getMessage())
+                    .contains("No matchers found for")
+                    .containsIgnoringCase("Not(?)");
+        }
+    }
+
+    @Test
+    public void should_scream_when_not_enough_matchers_inside_or_AddtionalMatcher() {
+        try {
+            mock.simpleMethod(AdditionalMatchers.or(eq("jkl"), "asd"));
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e.getMessage())
+                    .containsIgnoringCase("inside additional matcher Or(?)")
+                    .contains("2 sub matchers expected")
+                    .contains("1 recorded");
+        }
+    }
+
+    @Test
+    public void should_scream_when_Matchers_count_dont_match_parameter_count() {
+        try {
+            mock.threeArgumentMethod(1, "asd", eq("asd"));
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e.getMessage())
+                    .contains("3 matchers expected")
+                    .contains("1 recorded");
+        }
+    }
+
+    @Test
+    public void should_mention_matcher_when_misuse_detected() {
+        // Given
+
+
+        // When
+        Result run = new JUnitCore().run(ObjectMatcherMisuseOnPrimitiveSite.class);
+
+        // Then
+
+        assertThat(run.getFailures()).hasSize(2);
+        assertThat(run.getFailures().get(0).getException()).isInstanceOf(NullPointerException.class)
+                                                           .hasMessage(null);
+        assertThat(run.getFailures().get(1).getException()).isInstanceOf(InvalidUseOfMatchersException.class)
+                                                           .hasMessageContaining("primitive alternatives");
+        new StateMaster().reset();
+
+    }
+
+    @RunWith(MockitoJUnitRunner.class)
+    public static class ObjectMatcherMisuseOnPrimitiveSite {
+        @Test
+        public void fails_with_NPE() {
+            IMethods mock = Mockito.mock(IMethods.class);
+            doNothing().when(mock)
+                       .twoArgumentMethod(eq(73),
+                                          (Integer) any()); // <= Raise NPE on this call site
+        }
+
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/MatchersMixedWithRawArgumentsTest.java b/src/test/java/org/mockitousage/matchers/MatchersMixedWithRawArgumentsTest.java
new file mode 100644
index 0000000..99cf81b
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/MatchersMixedWithRawArgumentsTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.verify;
+
+public class MatchersMixedWithRawArgumentsTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    //description of an idea:
+    //types of arguments and descriptor value that identifies matcher:
+    //Object: objenesis instance to check for identity
+    //boolean: false
+    //byte: max-1
+    //short: max-1
+    //int: max-1
+    //long: max-1
+    //char: 'x'
+    //double: max-1
+    //float: max-1
+
+    //1. how objenesis deal with primitive arrays (like byte[])?
+    //2. Analisys of all matchers used by R2 project finished before anyObject() and so far proves it's a good idea.
+
+    @Ignore("prototyping new feature that allows to avoid eq() matchers when raw args passed")
+    @Test
+    public void shouldAllowMixingRawArgumentsWithMatchers() {
+        mock.varargs("1", "2", "3");
+        verify(mock).varargs("1", anyString(), "3");
+
+        verify(mock).varargs(anyBoolean(), false);
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/MatchersTest.java b/src/test/java/org/mockitousage/matchers/MatchersTest.java
new file mode 100644
index 0000000..f151a84
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/MatchersTest.java
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.RandomAccess;
+import java.util.regex.Pattern;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotSame;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalMatchers.and;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.AdditionalMatchers.cmpEq;
+import static org.mockito.AdditionalMatchers.eq;
+import static org.mockito.AdditionalMatchers.find;
+import static org.mockito.AdditionalMatchers.geq;
+import static org.mockito.AdditionalMatchers.gt;
+import static org.mockito.AdditionalMatchers.leq;
+import static org.mockito.AdditionalMatchers.lt;
+import static org.mockito.AdditionalMatchers.not;
+import static org.mockito.AdditionalMatchers.or;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyByte;
+import static org.mockito.Mockito.anyChar;
+import static org.mockito.Mockito.anyDouble;
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyObject;
+import static org.mockito.Mockito.anyShort;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.contains;
+import static org.mockito.Mockito.endsWith;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.isNotNull;
+import static org.mockito.Mockito.isNull;
+import static org.mockito.Mockito.matches;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.notNull;
+import static org.mockito.Mockito.same;
+import static org.mockito.Mockito.startsWith;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+@SuppressWarnings("unchecked")
+public class MatchersTest extends TestBase {
+    private IMethods mock = Mockito.mock(IMethods.class);
+
+    @Test
+    public void and_overloaded() {
+        when(mock.oneArg(and(eq(false), eq(false)))).thenReturn("0");
+        when(mock.oneArg(and(eq((byte) 1), eq((byte) 1)))).thenReturn("1");
+        when(mock.oneArg(and(eq('a'), eq('a')))).thenReturn("2");
+        when(mock.oneArg(and(eq((double) 1), eq((double) 1)))).thenReturn("3");
+        when(mock.oneArg(and(eq((float) 1), eq((float) 1)))).thenReturn("4");
+        when(mock.oneArg(and(eq((int) 1), eq((int) 1)))).thenReturn("5");
+        when(mock.oneArg(and(eq((long) 1), eq((long) 1)))).thenReturn("6");
+        when(mock.oneArg(and(eq((short) 1), eq((short) 1)))).thenReturn("7");
+        when(mock.oneArg(and(contains("a"), contains("d")))).thenReturn("8");
+        when(mock.oneArg(and(isA(Class.class), eq(Object.class)))).thenReturn("9");
+
+        assertEquals("0", mock.oneArg(false));
+        assertEquals(null, mock.oneArg(true));
+
+        assertEquals("1", mock.oneArg((byte) 1));
+        assertEquals("2", mock.oneArg('a'));
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("4", mock.oneArg((float) 1));
+        assertEquals("5", mock.oneArg((int) 1));
+        assertEquals("6", mock.oneArg((long) 1));
+        assertEquals("7", mock.oneArg((short) 1));
+
+        assertEquals("8", mock.oneArg("abcde"));
+        assertEquals(null, mock.oneArg("aaaaa"));
+
+        assertEquals("9", mock.oneArg(Object.class));
+    }
+
+    @Test
+    public void or_overloaded() {
+        when(mock.oneArg(or(eq(false), eq(true)))).thenReturn("0");
+        when(mock.oneArg(or(eq((byte) 1), eq((byte) 2)))).thenReturn("1");
+        when(mock.oneArg(or(eq((char) 1), eq((char) 2)))).thenReturn("2");
+        when(mock.oneArg(or(eq((double) 1), eq((double) 2)))).thenReturn("3");
+        when(mock.oneArg(or(eq((float) 1), eq((float) 2)))).thenReturn("4");
+        when(mock.oneArg(or(eq((int) 1), eq((int) 2)))).thenReturn("5");
+        when(mock.oneArg(or(eq((long) 1), eq((long) 2)))).thenReturn("6");
+        when(mock.oneArg(or(eq((short) 1), eq((short) 2)))).thenReturn("7");
+        when(mock.oneArg(or(eq("asd"), eq("jkl")))).thenReturn("8");
+        when(mock.oneArg(or(eq(this.getClass()), eq(Object.class)))).thenReturn("9");
+
+        assertEquals("0", mock.oneArg(true));
+        assertEquals("0", mock.oneArg(false));
+
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals("2", mock.oneArg((char) 1));
+        assertEquals("3", mock.oneArg((double) 2));
+        assertEquals("4", mock.oneArg((float) 1));
+        assertEquals("5", mock.oneArg((int) 2));
+        assertEquals("6", mock.oneArg((long) 1));
+        assertEquals("7", mock.oneArg((short) 1));
+
+        assertEquals("8", mock.oneArg("jkl"));
+        assertEquals("8", mock.oneArg("asd"));
+        assertEquals(null, mock.oneArg("asdjkl"));
+
+        assertEquals("9", mock.oneArg(Object.class));
+        assertEquals(null, mock.oneArg(String.class));
+    }
+
+    @Test
+    public void not_overloaded() {
+        when(mock.oneArg(not(eq(false)))).thenReturn("0");
+        when(mock.oneArg(not(eq((byte) 1)))).thenReturn("1");
+        when(mock.oneArg(not(eq('a')))).thenReturn("2");
+        when(mock.oneArg(not(eq((double) 1)))).thenReturn("3");
+        when(mock.oneArg(not(eq((float) 1)))).thenReturn("4");
+        when(mock.oneArg(not(eq((int) 1)))).thenReturn("5");
+        when(mock.oneArg(not(eq((long) 1)))).thenReturn("6");
+        when(mock.oneArg(not(eq((short) 1)))).thenReturn("7");
+        when(mock.oneArg(not(contains("a")))).thenReturn("8");
+        when(mock.oneArg(not(isA(Class.class)))).thenReturn("9");
+
+        assertEquals("0", mock.oneArg(true));
+        assertEquals(null, mock.oneArg(false));
+
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals("2", mock.oneArg('b'));
+        assertEquals("3", mock.oneArg((double) 2));
+        assertEquals("4", mock.oneArg((float) 2));
+        assertEquals("5", mock.oneArg((int) 2));
+        assertEquals("6", mock.oneArg((long) 2));
+        assertEquals("7", mock.oneArg((short) 2));
+        assertEquals("8", mock.oneArg("bcde"));
+
+        assertEquals("9", mock.oneArg(new Object()));
+        assertEquals(null, mock.oneArg(Class.class));
+    }
+
+    @Test
+    public void less_or_equal_overloaded() {
+        when(mock.oneArg(leq((byte) 1))).thenReturn("1");
+        when(mock.oneArg(leq((double) 1))).thenReturn("3");
+        when(mock.oneArg(leq((float) 1))).thenReturn("4");
+        when(mock.oneArg(leq((int) 1))).thenReturn("5");
+        when(mock.oneArg(leq((long) 1))).thenReturn("6");
+        when(mock.oneArg(leq((short) 1))).thenReturn("7");
+        when(mock.oneArg(leq(new BigDecimal("1")))).thenReturn("8");
+
+        assertEquals("1", mock.oneArg((byte) 1));
+        assertEquals(null, mock.oneArg((byte) 2));
+
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("7", mock.oneArg((short) 0));
+        assertEquals("4", mock.oneArg((float) -5));
+        assertEquals("5", mock.oneArg((int) -2));
+        assertEquals("6", mock.oneArg((long) -3));
+
+        assertEquals("8", mock.oneArg(new BigDecimal("0.5")));
+        assertEquals(null, mock.oneArg(new BigDecimal("1.1")));
+    }
+
+    @Test
+    public void less_than_overloaded() {
+        when(mock.oneArg(lt((byte) 1))).thenReturn("1");
+        when(mock.oneArg(lt((double) 1))).thenReturn("3");
+        when(mock.oneArg(lt((float) 1))).thenReturn("4");
+        when(mock.oneArg(lt((int) 1))).thenReturn("5");
+        when(mock.oneArg(lt((long) 1))).thenReturn("6");
+        when(mock.oneArg(lt((short) 1))).thenReturn("7");
+        when(mock.oneArg(lt(new BigDecimal("1")))).thenReturn("8");
+
+        assertEquals("1", mock.oneArg((byte) 0));
+        assertEquals(null, mock.oneArg((byte) 1));
+
+        assertEquals("3", mock.oneArg((double) 0));
+        assertEquals("7", mock.oneArg((short) 0));
+        assertEquals("4", mock.oneArg((float) -4));
+        assertEquals("5", mock.oneArg((int) -34));
+        assertEquals("6", mock.oneArg((long) -6));
+
+        assertEquals("8", mock.oneArg(new BigDecimal("0.5")));
+        assertEquals(null, mock.oneArg(new BigDecimal("23")));
+    }
+
+    @Test
+    public void greater_or_equal_matcher_overloaded() {
+        when(mock.oneArg(geq((byte) 1))).thenReturn("1");
+        when(mock.oneArg(geq((double) 1))).thenReturn("3");
+        when(mock.oneArg(geq((float) 1))).thenReturn("4");
+        when(mock.oneArg(geq((int) 1))).thenReturn("5");
+        when(mock.oneArg(geq((long) 1))).thenReturn("6");
+        when(mock.oneArg(geq((short) 1))).thenReturn("7");
+        when(mock.oneArg(geq(new BigDecimal("1")))).thenReturn("8");
+
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals(null, mock.oneArg((byte) 0));
+
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("7", mock.oneArg((short) 2));
+        assertEquals("4", mock.oneArg((float) 3));
+        assertEquals("5", mock.oneArg((int) 4));
+        assertEquals("6", mock.oneArg((long) 5));
+
+        assertEquals("8", mock.oneArg(new BigDecimal("1.00")));
+        assertEquals(null, mock.oneArg(new BigDecimal("0.9")));
+    }
+
+    @Test
+    public void greater_than_matcher_overloaded() {
+        when(mock.oneArg(gt((byte) 1))).thenReturn("1");
+        when(mock.oneArg(gt((double) 1))).thenReturn("3");
+        when(mock.oneArg(gt((float) 1))).thenReturn("4");
+        when(mock.oneArg(gt((int) 1))).thenReturn("5");
+        when(mock.oneArg(gt((long) 1))).thenReturn("6");
+        when(mock.oneArg(gt((short) 1))).thenReturn("7");
+        when(mock.oneArg(gt(new BigDecimal("1")))).thenReturn("8");
+
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals(null, mock.oneArg((byte) 1));
+
+        assertEquals("3", mock.oneArg((double) 2));
+        assertEquals("7", mock.oneArg((short) 2));
+        assertEquals("4", mock.oneArg((float) 3));
+        assertEquals("5", mock.oneArg((int) 2));
+        assertEquals("6", mock.oneArg((long) 5));
+
+        assertEquals("8", mock.oneArg(new BigDecimal("1.5")));
+        assertEquals(null, mock.oneArg(new BigDecimal("0.9")));
+    }
+
+    @Test
+    public void compare_to_matcher() {
+        when(mock.oneArg(cmpEq(new BigDecimal("1.5")))).thenReturn("0");
+
+        assertEquals("0", mock.oneArg(new BigDecimal("1.50")));
+        assertEquals(null, mock.oneArg(new BigDecimal("1.51")));
+    }
+
+    @Test
+    public void any_String_matcher() {
+        when(mock.oneArg(anyString())).thenReturn("matched");
+
+        assertEquals("matched", mock.oneArg(""));
+        assertEquals("matched", mock.oneArg("any string"));
+        assertEquals(null, mock.oneArg((String) null));
+    }
+
+    @Test
+    public void any_matcher() {
+        when(mock.forObject(any())).thenReturn("matched");
+
+        assertEquals("matched", mock.forObject(123));
+        assertEquals("matched", mock.forObject("any string"));
+        assertEquals("matched", mock.forObject("any string"));
+        assertEquals("matched", mock.forObject((Object) null));
+    }
+
+    @Test
+    public void any_T_matcher() {
+        when(mock.oneArg(anyBoolean())).thenReturn("0");
+        when(mock.oneArg(anyByte())).thenReturn("1");
+        when(mock.oneArg(anyChar())).thenReturn("2");
+        when(mock.oneArg(anyDouble())).thenReturn("3");
+        when(mock.oneArg(anyFloat())).thenReturn("4");
+        when(mock.oneArg(anyInt())).thenReturn("5");
+        when(mock.oneArg(anyLong())).thenReturn("6");
+        when(mock.oneArg(anyShort())).thenReturn("7");
+        when(mock.oneArg((String) anyObject())).thenReturn("8");
+        when(mock.oneArg((Object) anyObject())).thenReturn("9");
+        when(mock.oneArg(any(RandomAccess.class))).thenReturn("10");
+
+        assertEquals("0", mock.oneArg(true));
+        assertEquals("0", mock.oneArg(false));
+
+        assertEquals("1", mock.oneArg((byte) 1));
+        assertEquals("2", mock.oneArg((char) 1));
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("4", mock.oneArg((float) 889));
+        assertEquals("5", mock.oneArg((int) 1));
+        assertEquals("6", mock.oneArg((long) 1));
+        assertEquals("7", mock.oneArg((short) 1));
+        assertEquals("8", mock.oneArg("Test"));
+
+        assertEquals("9", mock.oneArg(new Object()));
+        assertEquals("9", mock.oneArg(new HashMap()));
+
+        assertEquals("10", mock.oneArg(new ArrayList()));
+    }
+
+    @Test
+    public void should_array_equals_deal_with_null_array() throws Exception {
+        Object[] nullArray = null;
+        when(mock.oneArray(aryEq(nullArray))).thenReturn("null");
+
+        assertEquals("null", mock.oneArray(nullArray));
+
+        mock = mock(IMethods.class);
+
+        try {
+            verify(mock).oneArray(aryEq(nullArray));
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("oneArray(null)");
+        }
+    }
+
+    @Test
+    public void should_use_smart_equals_for_arrays() throws Exception {
+        //issue 143
+        mock.arrayMethod(new String[]{"one"});
+        verify(mock).arrayMethod(eq(new String[]{"one"}));
+        verify(mock).arrayMethod(new String[]{"one"});
+    }
+
+    @Test
+    public void should_use_smart_equals_for_primitive_arrays() throws Exception {
+        //issue 143
+        mock.objectArgMethod(new int[]{1, 2});
+        verify(mock).objectArgMethod(eq(new int[]{1, 2}));
+        verify(mock).objectArgMethod(new int[]{1, 2});
+    }
+
+    @Test(expected = ArgumentsAreDifferent.class)
+    public void array_equals_should_throw_ArgumentsAreDifferentException_for_non_matching_arguments() {
+        List<Object> list = Mockito.mock(List.class);
+
+        list.add("test"); // testing fix for issue 20
+        list.contains(new Object[]{"1"});
+
+        Mockito.verify(list).contains(new Object[]{"1", "2", "3"});
+    }
+
+    @Test
+    public void array_equals_matcher() {
+        when(mock.oneArray(aryEq(new boolean[]{true, false, false}))).thenReturn("0");
+        when(mock.oneArray(aryEq(new byte[]{1}))).thenReturn("1");
+        when(mock.oneArray(aryEq(new char[]{1}))).thenReturn("2");
+        when(mock.oneArray(aryEq(new double[]{1}))).thenReturn("3");
+        when(mock.oneArray(aryEq(new float[]{1}))).thenReturn("4");
+        when(mock.oneArray(aryEq(new int[]{1}))).thenReturn("5");
+        when(mock.oneArray(aryEq(new long[]{1}))).thenReturn("6");
+        when(mock.oneArray(aryEq(new short[]{1}))).thenReturn("7");
+        when(mock.oneArray(aryEq(new String[]{"Test"}))).thenReturn("8");
+        when(mock.oneArray(aryEq(new Object[]{"Test", new Integer(4)}))).thenReturn("9");
+
+        assertEquals("0", mock.oneArray(new boolean[]{true, false, false}));
+        assertEquals("1", mock.oneArray(new byte[]{1}));
+        assertEquals("2", mock.oneArray(new char[]{1}));
+        assertEquals("3", mock.oneArray(new double[]{1}));
+        assertEquals("4", mock.oneArray(new float[]{1}));
+        assertEquals("5", mock.oneArray(new int[]{1}));
+        assertEquals("6", mock.oneArray(new long[]{1}));
+        assertEquals("7", mock.oneArray(new short[]{1}));
+        assertEquals("8", mock.oneArray(new String[]{"Test"}));
+        assertEquals("9", mock.oneArray(new Object[]{"Test", new Integer(4)}));
+
+        assertEquals(null, mock.oneArray(new Object[]{"Test", new Integer(999)}));
+        assertEquals(null, mock.oneArray(new Object[]{"Test", new Integer(4), "x"}));
+
+        assertEquals(null, mock.oneArray(new boolean[]{true, false}));
+        assertEquals(null, mock.oneArray(new boolean[]{true, true, false}));
+    }
+
+    @Test
+    public void greater_or_equal_matcher() {
+        when(mock.oneArg(geq(7))).thenReturn(">= 7");
+        when(mock.oneArg(lt(7))).thenReturn("< 7");
+
+        assertEquals(">= 7", mock.oneArg(7));
+        assertEquals(">= 7", mock.oneArg(8));
+        assertEquals(">= 7", mock.oneArg(9));
+
+        assertEquals("< 7", mock.oneArg(6));
+        assertEquals("< 7", mock.oneArg(6));
+    }
+
+    @Test
+    public void greater_than_matcher() {
+        when(mock.oneArg(gt(7))).thenReturn("> 7");
+        when(mock.oneArg(leq(7))).thenReturn("<= 7");
+
+        assertEquals("> 7", mock.oneArg(8));
+        assertEquals("> 7", mock.oneArg(9));
+        assertEquals("> 7", mock.oneArg(10));
+
+        assertEquals("<= 7", mock.oneArg(7));
+        assertEquals("<= 7", mock.oneArg(6));
+    }
+
+    @Test
+    public void less_or_equal_matcher() {
+        when(mock.oneArg(leq(7))).thenReturn("<= 7");
+        when(mock.oneArg(gt(7))).thenReturn("> 7");
+
+        assertEquals("<= 7", mock.oneArg(7));
+        assertEquals("<= 7", mock.oneArg(6));
+        assertEquals("<= 7", mock.oneArg(5));
+
+        assertEquals("> 7", mock.oneArg(8));
+        assertEquals("> 7", mock.oneArg(9));
+    }
+
+    @Test
+    public void less_than_matcher() {
+        when(mock.oneArg(lt(7))).thenReturn("< 7");
+        when(mock.oneArg(geq(7))).thenReturn(">= 7");
+
+        assertEquals("< 7", mock.oneArg(5));
+        assertEquals("< 7", mock.oneArg(6));
+        assertEquals("< 7", mock.oneArg(4));
+
+        assertEquals(">= 7", mock.oneArg(7));
+        assertEquals(">= 7", mock.oneArg(8));
+    }
+
+    @Test
+    public void or_matcher() {
+        when(mock.oneArg(anyInt())).thenReturn("other");
+        when(mock.oneArg(or(eq(7), eq(9)))).thenReturn("7 or 9");
+
+        assertEquals("other", mock.oneArg(10));
+        assertEquals("7 or 9", mock.oneArg(7));
+        assertEquals("7 or 9", mock.oneArg(9));
+    }
+
+    @Test
+    public void null_matcher() {
+        when(mock.threeArgumentMethod(eq(1), isNull(), eq(""))).thenReturn("1");
+        when(mock.threeArgumentMethod(eq(1), not(isNull()), eq(""))).thenReturn("2");
+
+        assertEquals("1", mock.threeArgumentMethod(1, null, ""));
+        assertEquals("2", mock.threeArgumentMethod(1, new Object(), ""));
+    }
+
+    @Test
+    public void null_matcher_for_primitive_wrappers() {
+        when(mock.forBoolean(isNull(Boolean.class))).thenReturn("ok");
+        when(mock.forInteger(isNull(Integer.class))).thenReturn("ok");
+        when(mock.forLong(isNull(Long.class))).thenReturn("ok");
+        when(mock.forByte(isNull(Byte.class))).thenReturn("ok");
+        when(mock.forShort(isNull(Short.class))).thenReturn("ok");
+        when(mock.forCharacter(isNull(Character.class))).thenReturn("ok");
+        when(mock.forDouble(isNull(Double.class))).thenReturn("ok");
+        when(mock.forFloat(isNull(Float.class))).thenReturn("ok");
+
+        assertEquals("ok", mock.forBoolean(null));
+        assertEquals("ok", mock.forInteger(null));
+        assertEquals("ok", mock.forLong(null));
+        assertEquals("ok", mock.forByte(null));
+        assertEquals("ok", mock.forShort(null));
+        assertEquals("ok", mock.forCharacter(null));
+        assertEquals("ok", mock.forDouble(null));
+        assertEquals("ok", mock.forFloat(null));
+    }
+
+    @Test
+    public void not_null_matcher() {
+        when(mock.threeArgumentMethod(eq(1), notNull(), eq(""))).thenReturn("1");
+        when(mock.threeArgumentMethod(eq(1), not(isNotNull()), eq(""))).thenReturn("2");
+
+        assertEquals("1", mock.threeArgumentMethod(1, new Object(), ""));
+        assertEquals("2", mock.threeArgumentMethod(1, null, ""));
+    }
+
+    @Test
+    public void find_matcher() {
+        when(mock.oneArg(find("([a-z]+)\\d"))).thenReturn("1");
+
+        assertEquals("1", mock.oneArg("ab12"));
+        assertEquals(null, mock.oneArg("12345"));
+        assertEquals(null, mock.oneArg((Object) null));
+    }
+
+    @Test
+    public void matches_matcher() {
+        when(mock.oneArg(matches("[a-z]+\\d\\d"))).thenReturn("1");
+        when(mock.oneArg(matches("\\d\\d\\d"))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg("a12"));
+        assertEquals("2", mock.oneArg("131"));
+        assertEquals(null, mock.oneArg("blah"));
+    }
+
+    @Test
+    public void matches_Pattern_matcher() {
+        when(mock.oneArg(matches(Pattern.compile("[a-z]+\\d\\d")))).thenReturn("1");
+        when(mock.oneArg(matches(Pattern.compile("\\d\\d\\d")))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg("a12"));
+        assertEquals("2", mock.oneArg("131"));
+        assertEquals(null, mock.oneArg("blah"));
+    }
+
+    @Test
+    public void contains_matcher() {
+        when(mock.oneArg(contains("ell"))).thenReturn("1");
+        when(mock.oneArg(contains("ld"))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg("hello"));
+        assertEquals("2", mock.oneArg("world"));
+        assertEquals(null, mock.oneArg("xlx"));
+    }
+
+    @Test
+    public void starts_with_matcher() {
+        when(mock.oneArg(startsWith("ab"))).thenReturn("1");
+        when(mock.oneArg(startsWith("bc"))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg("ab quake"));
+        assertEquals("2", mock.oneArg("bc quake"));
+        assertEquals(null, mock.oneArg("ba quake"));
+    }
+
+    @Test
+    public void ends_with_matcher() {
+        when(mock.oneArg(endsWith("ab"))).thenReturn("1");
+        when(mock.oneArg(endsWith("bc"))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg("xab"));
+        assertEquals("2", mock.oneArg("xbc"));
+        assertEquals(null, mock.oneArg("ac"));
+    }
+
+    @Test
+    public void delta_matcher() {
+        when(mock.oneArg(eq(1.0D, 0.1D))).thenReturn("1");
+        when(mock.oneArg(eq(2.0D, 0.1D))).thenReturn("2");
+        when(mock.oneArg(eq(1.0F, 0.1F))).thenReturn("3");
+        when(mock.oneArg(eq(2.0F, 0.1F))).thenReturn("4");
+        when(mock.oneArg(eq(2.0F, 0.1F))).thenReturn("4");
+
+        assertEquals("1", mock.oneArg(1.0));
+        assertEquals("1", mock.oneArg(0.91));
+        assertEquals("1", mock.oneArg(1.09));
+        assertEquals("2", mock.oneArg(2.0));
+
+        assertEquals("3", mock.oneArg(1.0F));
+        assertEquals("3", mock.oneArg(0.91F));
+        assertEquals("3", mock.oneArg(1.09F));
+        assertEquals("4", mock.oneArg(2.1F));
+
+        assertEquals(null, mock.oneArg(2.2F));
+    }
+
+    @Test
+    public void delta_matcher_prints_itself() {
+        try {
+            verify(mock).oneArg(eq(1.0D, 0.1D));
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("eq(1.0, 0.1)");
+        }
+    }
+
+    @Test
+    public void same_matcher() {
+        Object one = new String("1243");
+        Object two = new String("1243");
+        Object three = new String("1243");
+
+        assertNotSame(one, two);
+        assertEquals(one, two);
+        assertEquals(two, three);
+
+        when(mock.oneArg(same(one))).thenReturn("1");
+        when(mock.oneArg(same(two))).thenReturn("2");
+
+        assertEquals("1", mock.oneArg(one));
+        assertEquals("2", mock.oneArg(two));
+        assertEquals(null, mock.oneArg(three));
+    }
+
+    @Test
+    public void eq_matcher_and_nulls() {
+        mock.simpleMethod((Object) null);
+
+        verify(mock).simpleMethod((Object) eq(null));
+    }
+
+    @Test
+    public void same_matcher_and_nulls() {
+        mock.simpleMethod((Object) null);
+
+        verify(mock).simpleMethod((Object) same(null));
+    }
+
+    @Test
+    public void nullable_matcher() throws Exception {
+        // imagine a Stream.of(...).map(c -> mock.oneArg(c))...
+        mock.oneArg((Character) null);
+        mock.oneArg(Character.valueOf('€'));
+
+        verify(mock, times(2)).oneArg(nullable(Character.class));
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/MoreMatchersTest.java b/src/test/java/org/mockitousage/matchers/MoreMatchersTest.java
new file mode 100644
index 0000000..3471fe0
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/MoreMatchersTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.*;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class MoreMatchersTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Test
+    public void should_help_out_with_unnecessary_casting() {
+        when(mock.objectArgMethod(any(String.class))).thenReturn("string");
+
+        assertEquals("string", mock.objectArgMethod("foo"));
+    }
+
+    @Test
+    public void any_should_be_actual_alias_to_anyObject() {
+        mock.simpleMethod((Object) null);
+
+        verify(mock).simpleMethod(any());
+        verify(mock).simpleMethod(anyObject());
+    }
+
+    @Test
+    public void any_class_should_be_actual_alias_to_isA() {
+        mock.simpleMethod(new ArrayList());
+
+        verify(mock).simpleMethod(isA(List.class));
+        verify(mock).simpleMethod(any(List.class));
+
+
+        mock.simpleMethod((String) null);
+        try {
+            verify(mock).simpleMethod(isA(String.class));
+            fail();
+        } catch (AssertionError ignored) { }
+        try {
+            verify(mock).simpleMethod(any(String.class));
+            fail();
+        } catch (AssertionError ignored) { }
+    }
+
+    @Test
+    public void should_help_out_with_unnecessary_casting_of_lists() {
+        //Below yields compiler warning:
+        //when(mock.listArgMethod(anyList())).thenReturn("list");
+        when(mock.listArgMethod(anyListOf(String.class))).thenReturn("list");
+
+        assertEquals("list", mock.listArgMethod(new LinkedList<String>()));
+        assertEquals("list", mock.listArgMethod(Collections.<String>emptyList()));
+    }
+
+    @Test
+    public void should_help_out_with_unnecessary_casting_of_sets() {
+        //Below yields compiler warning:
+        //when(mock.setArgMethod(anySet())).thenReturn("set");
+        when(mock.setArgMethod(anySetOf(String.class))).thenReturn("set");
+
+        assertEquals("set", mock.setArgMethod(new HashSet<String>()));
+        assertEquals("set", mock.setArgMethod(Collections.<String>emptySet()));
+    }
+
+    @Test
+    public void should_help_out_with_unnecessary_casting_of_maps() {
+        //Below yields compiler warning:
+        //when(mock.setArgMethod(anySet())).thenReturn("set");
+        when(mock.forMap(anyMapOf(String.class, String.class))).thenReturn("map");
+
+        assertEquals("map", mock.forMap(new HashMap<String, String>()));
+        assertEquals("map", mock.forMap(Collections.<String, String>emptyMap()));
+    }
+
+    @Test
+    public void should_help_out_with_unnecessary_casting_of_collections() {
+        //Below yields compiler warning:
+        //when(mock.setArgMethod(anySet())).thenReturn("set");
+        when(mock.collectionArgMethod(anyCollectionOf(String.class))).thenReturn("collection");
+
+        assertEquals("collection", mock.collectionArgMethod(new ArrayList<String>()));
+        assertEquals("collection", mock.collectionArgMethod(Collections.<String>emptyList()));
+    }
+
+    @Test
+    public void should_help_out_with_unnecessary_casting_of_iterables() {
+        //Below yields compiler warning:
+        //when(mock.setArgMethod(anySet())).thenReturn("set");
+        when(mock.iterableArgMethod(anyIterableOf(String.class))).thenReturn("iterable");
+
+        assertEquals("iterable", mock.iterableArgMethod(new ArrayList<String>()));
+        assertEquals("iterable", mock.iterableArgMethod(Collections.<String>emptyList()));
+    }
+
+    @Test
+    public void should_help_out_with_unnecessary_casting_of_nullity_checks() {
+        when(mock.objectArgMethod(isNull(LinkedList.class))).thenReturn("string");
+        when(mock.objectArgMethod(notNull(LinkedList.class))).thenReturn("string");
+        when(mock.objectArgMethod(isNotNull(LinkedList.class))).thenReturn("string");
+
+        assertEquals("string", mock.objectArgMethod(null));
+        assertEquals("string", mock.objectArgMethod("foo"));
+        assertEquals("string", mock.objectArgMethod("foo"));
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/matchers/NewMatchersTest.java b/src/test/java/org/mockitousage/matchers/NewMatchersTest.java
new file mode 100644
index 0000000..08c8eeb
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/NewMatchersTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.matchers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class NewMatchersTest extends TestBase {
+
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = Mockito.mock(IMethods.class);
+    }
+
+    @Test
+    public void shouldAllowAnyList() {
+        when(mock.forList(anyListOf(String.class))).thenReturn("matched");
+
+        assertEquals("matched", mock.forList(Arrays.asList("x", "y")));
+        assertEquals(null, mock.forList(null));
+
+        verify(mock, times(1)).forList(anyListOf(String.class));
+    }
+
+    @Test
+    public void shouldAllowAnyCollection() {
+        when(mock.forCollection(anyCollectionOf(String.class))).thenReturn("matched");
+
+        assertEquals("matched", mock.forCollection(Arrays.asList("x", "y")));
+        assertEquals(null, mock.forCollection(null));
+
+        verify(mock, times(1)).forCollection(anyCollectionOf(String.class));
+    }
+
+    @Test
+    public void shouldAllowAnyMap() {
+        when(mock.forMap(anyMapOf(String.class, String.class))).thenReturn("matched");
+
+        assertEquals("matched", mock.forMap(new HashMap<String, String>()));
+        assertEquals(null, mock.forMap(null));
+
+        verify(mock, times(1)).forMap(anyMapOf(String.class, String.class));
+    }
+
+    @Test
+    public void shouldAllowAnySet() {
+        when(mock.forSet(anySetOf(String.class))).thenReturn("matched");
+
+        assertEquals("matched", mock.forSet(new HashSet<String>()));
+        assertEquals(null, mock.forSet(null));
+
+        verify(mock, times(1)).forSet(anySetOf(String.class));
+    }
+
+    @Test
+    public void shouldAllowAnyIterable() {
+        when(mock.forIterable(anyIterableOf(String.class))).thenReturn("matched");
+
+        assertEquals("matched", mock.forIterable(new HashSet<String>()));
+        assertEquals(null, mock.forIterable(null));
+
+        verify(mock, times(1)).forIterable(anyIterableOf(String.class));
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/ReflectionMatchersTest.java b/src/test/java/org/mockitousage/matchers/ReflectionMatchersTest.java
new file mode 100644
index 0000000..84ad482
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/ReflectionMatchersTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Matchers.refEq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+@SuppressWarnings("all")
+public class ReflectionMatchersTest extends TestBase {
+
+    class Parent {
+        private int parentField;
+        protected String protectedParentField;
+        public Parent(int parentField, String protectedParentField) {
+            this.parentField = parentField;
+            this.protectedParentField = protectedParentField;
+        }
+    }
+
+    class Child extends Parent {
+        private int childFieldOne;
+        private Object childFieldTwo;
+        public Child(int parentField, String protectedParentField, int childFieldOne, Object childFieldTwo) {
+            super(parentField, protectedParentField);
+            this.childFieldOne = childFieldOne;
+            this.childFieldTwo = childFieldTwo;
+        }
+    }
+
+    interface MockMe {
+        void run(Child child);
+    }
+
+    MockMe mock;
+
+    @Before
+    public void setup() {
+        mock = mock(MockMe.class);
+
+        Child actual = new Child(1, "foo", 2, "bar");
+        mock.run(actual);
+    }
+
+    @Test
+    public void shouldMatchWhenFieldValuesEqual() throws Exception {
+        Child wanted = new Child(1, "foo", 2, "bar");
+        verify(mock).run(refEq(wanted));
+    }
+
+    @Test(expected=ArgumentsAreDifferent.class)
+    public void shouldNotMatchWhenFieldValuesDiffer() throws Exception {
+        Child wanted = new Child(1, "foo", 2, "bar XXX");
+        verify(mock).run(refEq(wanted));
+    }
+
+    @Test(expected=ArgumentsAreDifferent.class)
+    public void shouldNotMatchAgain() throws Exception {
+        Child wanted = new Child(1, "foo", 999, "bar");
+        verify(mock).run(refEq(wanted));
+    }
+
+    @Test(expected=ArgumentsAreDifferent.class)
+    public void shouldNotMatchYetAgain() throws Exception {
+        Child wanted = new Child(1, "XXXXX", 2, "bar");
+        verify(mock).run(refEq(wanted));
+    }
+
+    @Test(expected=ArgumentsAreDifferent.class)
+    public void shouldNotMatch() throws Exception {
+        Child wanted = new Child(234234, "foo", 2, "bar");
+        verify(mock).run(refEq(wanted));
+    }
+
+    @Test
+    public void shouldMatchWhenFieldValuesEqualWithOneFieldExcluded() throws Exception {
+        Child wanted = new Child(1, "foo", 2, "excluded");
+        verify(mock).run(refEq(wanted, "childFieldTwo"));
+    }
+
+    @Test
+    public void shouldMatchWhenFieldValuesEqualWithTwoFieldsExcluded() throws Exception {
+        Child wanted = new Child(234234, "foo", 2, "excluded");
+        verify(mock).run(refEq(wanted, "childFieldTwo", "parentField"));
+        verify(mock).run(refEq(wanted, "parentField", "childFieldTwo"));
+    }
+
+    @Test(expected=ArgumentsAreDifferent.class)
+    public void shouldNotMatchWithFieldsExclusion() throws Exception {
+        Child wanted = new Child(234234, "foo", 2, "excluded");
+        verify(mock).run(refEq(wanted, "childFieldTwo"));
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/VarargsTest.java b/src/test/java/org/mockitousage/matchers/VarargsTest.java
new file mode 100644
index 0000000..f7c5b6b
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/VarargsTest.java
@@ -0,0 +1,341 @@
+package org.mockitousage.matchers;
+
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNotNull;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.assertj.core.api.AbstractListAssert;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.Condition;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+
+public class VarargsTest {
+
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+    @Captor
+    private ArgumentCaptor<String> captor;
+    @Mock
+    private IMethods mock;
+
+    private static final Condition<Object> NULL = new Condition<Object>() {
+
+        @Override
+        public boolean matches(Object value) {
+            return value == null;
+        }
+    };
+
+    @Test
+    public void shouldMatchVarArgs_noArgs() {
+        mock.varargs();
+
+        verify(mock).varargs();
+    }
+
+    @Test
+    @Ignore("This test must succeed but is fails currently, see github issue #616")
+    public void shouldMatchEmptyVarArgs_noArgsIsNotNull() {
+        mock.varargs();
+
+        verify(mock).varargs(isNotNull());
+    }
+
+    @Test
+    @Ignore("This test must succeed but is fails currently, see github issue #616")
+    public void shouldMatchEmptyVarArgs_noArgsIsNull() {
+        mock.varargs();
+
+        verify(mock).varargs(isNull());
+    }
+
+    @Test
+    @Ignore("This test must succeed but is fails currently, see github issue #616")
+    public void shouldMatchEmptyVarArgs_noArgsIsNotNullArray() {
+        mock.varargs();
+
+        verify(mock).varargs((String[]) isNotNull());
+    }
+
+    @Test
+    public void shouldMatchVarArgs_oneNullArg_eqNull() {
+        Object arg = null;
+        mock.varargs(arg);
+
+        verify(mock).varargs(eq(null));
+    }
+
+    @Test
+    public void shouldMatchVarArgs_oneNullArg_isNull() {
+        Object arg = null;
+        mock.varargs(arg);
+
+        verify(mock).varargs(isNull());
+    }
+
+    @Test
+    public void shouldMatchVarArgs_nullArrayArg() {
+        Object[] argArray = null;
+        mock.varargs(argArray);
+
+        verify(mock).varargs(isNull());
+    }
+
+    @Test
+    public void shouldnotMatchVarArgs_twoArgsOneMatcher() {
+        mock.varargs("1", "1");
+
+        exception.expectMessage("Argument(s) are different");
+
+        verify(mock).varargs(eq("1"));
+    }
+
+    @Test
+    public void shouldMatchVarArgs_emptyVarArgsOneAnyMatcher() {
+        mock.varargs();
+
+        verify(mock).varargs((String[])any()); // any() -> VarargMatcher
+    }
+
+    @Test
+    public void shouldMatchVarArgs_oneArgsOneAnyMatcher() {
+        mock.varargs(1);
+
+        verify(mock).varargs(any()); // any() -> VarargMatcher
+    }
+
+    @Test
+    public void shouldMatchVarArgs_twoArgsOneAnyMatcher() {
+        mock.varargs(1, 2);
+
+        verify(mock).varargs(any()); // any() -> VarargMatcher
+    }
+
+    @Test
+    public void shouldMatchVarArgs_twoArgsTwoAnyMatcher() {
+        mock.varargs(1, 2);
+
+        verify(mock).varargs(any(), any()); // any() -> VarargMatcher
+    }
+
+    @Test
+    public void shouldMatchVarArgs_twoArgsThreeAnyMatcher() {
+        mock.varargs(1, 2);
+
+        exception.expectMessage("Argument(s) are different");
+
+        verify(mock).varargs(any(), any(), any()); //any() -> VarargMatcher
+    }
+
+    @Test
+    public void shouldMatchVarArgs_oneNullArgument() {
+        mock.varargs("1", null);
+
+        verify(mock).varargs(eq("1"), (String) isNull());
+    }
+
+    @Test
+    public void shouldMatchVarArgs_onebyte() {
+        mock.varargsbyte((byte) 1);
+
+        verify(mock).varargsbyte(eq((byte) 1));
+    }
+
+    @Test
+    public void shouldMatchVarArgs_nullByteArray() {
+        mock.varargsbyte(null);
+
+        verify(mock).varargsbyte((byte[]) isNull());
+    }
+
+    @Test
+    public void shouldMatchVarArgs_emptyByteArray() {
+        mock.varargsbyte();
+
+        verify(mock).varargsbyte();
+    }
+
+    @Test
+    @Ignore
+    public void shouldMatchEmptyVarArgs_emptyArrayIsNotNull() {
+        mock.varargsbyte();
+
+        verify(mock).varargsbyte((byte[]) isNotNull());
+    }
+
+    @Test
+    public void shouldMatchVarArgs_oneArgIsNotNull() {
+        mock.varargsbyte((byte) 1);
+
+        verify(mock).varargsbyte((byte[]) isNotNull());
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_noArgs() {
+        mock.varargs();
+
+        verify(mock).varargs(captor.capture());
+
+        assertThat(captor).isEmpty();
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_oneNullArg_eqNull() {
+        String arg = null;
+        mock.varargs(arg);
+
+        verify(mock).varargs(captor.capture());
+
+        assertThat(captor).areExactly(1, NULL);
+    }
+
+    /**
+     * Relates to Github issue #583 "ArgumentCaptor: NPE when an null array is
+     * passed to a varargs method"
+     */
+    @Test
+    public void shouldCaptureVarArgs_nullArrayArg() {
+        String[] argArray = null;
+        mock.varargs(argArray);
+
+        verify(mock).varargs(captor.capture());
+        assertThat(captor).areExactly(1, NULL);
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_twoArgsOneCapture() {
+        mock.varargs("1", "2");
+
+        verify(mock).varargs(captor.capture());
+
+        assertThat(captor).contains("1", "2");
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_twoArgsTwoCaptures() {
+        mock.varargs("1", "2");
+
+        verify(mock).varargs(captor.capture(), captor.capture());
+
+        assertThat(captor).contains("1", "2");
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_oneNullArgument() {
+        mock.varargs("1", null);
+
+        verify(mock).varargs(captor.capture());
+
+        assertThat(captor).contains("1", (String) null);
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_oneNullArgument2() {
+        mock.varargs("1", null);
+
+        verify(mock).varargs(captor.capture(), captor.capture());
+
+        assertThat(captor).contains("1", (String) null);
+    }
+
+    @Test
+    public void shouldNotCaptureVarArgs_3args2captures() {
+        mock.varargs("1", "2", "3");
+
+        exception.expect(ArgumentsAreDifferent.class);
+
+        verify(mock).varargs(captor.capture(), captor.capture());
+
+    }
+
+    @Test
+    public void shouldCaptureVarArgs_3argsCaptorMatcherMix() {
+        mock.varargs("1", "2", "3");
+
+        verify(mock).varargs(captor.capture(), eq("2"), captor.capture());
+
+        assertThat(captor).containsExactly("1", "3");
+
+    }
+
+    @Test
+    public void shouldNotCaptureVarArgs_3argsCaptorMatcherMix() {
+        mock.varargs("1", "2", "3");
+
+        try {
+            verify(mock).varargs(captor.capture(), eq("X"), captor.capture());
+            fail("The verification must fail, cause the second arg was not 'X' as expected!");
+        } catch (ArgumentsAreDifferent expected) {
+        }
+
+        assertThat(captor).isEmpty();
+
+    }
+
+    @Test
+    public void shouldNotCaptureVarArgs_1args2captures() {
+        mock.varargs("1");
+
+        exception.expect(ArgumentsAreDifferent.class);
+
+        verify(mock).varargs(captor.capture(), captor.capture());
+
+    }
+
+    /**
+     * As of v2.0.0-beta.118 this test fails. Once the github issues:
+     * <ul>
+     * <li>'#584 ArgumentCaptor can't capture varargs-arrays
+     * <li>#565 ArgumentCaptor should be type aware' are fixed this test must
+     * succeed
+     * </ul>
+     *
+     * @throws Exception
+     */
+    @Test
+    @Ignore("Blocked by github issue: #584 & #565")
+    public void shouldCaptureVarArgsAsArray() {
+        mock.varargs("1", "2");
+
+        ArgumentCaptor<String[]> varargCaptor = ArgumentCaptor.forClass(String[].class);
+
+        verify(mock).varargs(varargCaptor.capture());
+
+        assertThat(varargCaptor).containsExactly(new String[] { "1", "2" });
+    }
+
+    @Test
+    public void shouldNotMatchRegualrAndVaraArgs()   {
+        mock.varargsString(1, "a","b");
+
+        exception.expect(ArgumentsAreDifferent.class);
+
+        verify(mock).varargsString(1);
+    }
+    @Test
+    public void shouldNotMatchVaraArgs()   {
+        when(mock.varargsObject(1, "a","b")).thenReturn("OK");
+
+        Assertions.assertThat(mock.varargsObject(1)).isNull();
+    }
+
+    private static <T> AbstractListAssert<?, ?, T> assertThat(ArgumentCaptor<T> captor) {
+        return Assertions.assertThat(captor.getAllValues());
+    }
+}
diff --git a/src/test/java/org/mockitousage/matchers/VerificationAndStubbingUsingMatchersTest.java b/src/test/java/org/mockitousage/matchers/VerificationAndStubbingUsingMatchersTest.java
new file mode 100644
index 0000000..80a27f1
--- /dev/null
+++ b/src/test/java/org/mockitousage/matchers/VerificationAndStubbingUsingMatchersTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.matchers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class VerificationAndStubbingUsingMatchersTest extends TestBase {
+    private IMethods one;
+    private IMethods two;
+    private IMethods three;
+
+    @Before
+    public void setUp() {
+        one = mock(IMethods.class);
+        two = mock(IMethods.class);
+        three = mock(IMethods.class);
+    }
+
+    @Test
+    public void shouldStubUsingMatchers() {
+        when(one.simpleMethod(2)).thenReturn("2");
+        when(two.simpleMethod(anyString())).thenReturn("any");
+        when(three.simpleMethod(startsWith("test"))).thenThrow(new RuntimeException());
+
+        assertEquals(null, one.simpleMethod(1));
+        assertEquals("2", one.simpleMethod(2));
+
+        assertEquals("any", two.simpleMethod("two"));
+        assertEquals("any", two.simpleMethod("two again"));
+
+        assertEquals(null, three.simpleMethod("three"));
+        assertEquals(null, three.simpleMethod("three again"));
+
+        try {
+            three.simpleMethod("test three again");
+            fail();
+        } catch (RuntimeException e) {}
+    }
+
+    @Test
+    public void shouldVerifyUsingMatchers() {
+        doThrow(new RuntimeException()).when(one).oneArg(true);
+        when(three.varargsObject(5, "first arg", "second arg")).thenReturn("stubbed");
+
+        try {
+            one.oneArg(true);
+            fail();
+        } catch (RuntimeException e) {}
+
+        one.simpleMethod(100);
+        two.simpleMethod("test Mockito");
+        three.varargsObject(10, "first arg", "second arg");
+
+        assertEquals("stubbed", three.varargsObject(5, "first arg", "second arg"));
+
+        verify(one).oneArg(eq(true));
+        verify(one).simpleMethod(anyInt());
+        verify(two).simpleMethod(startsWith("test"));
+        verify(three).varargsObject(5, "first arg", "second arg");
+        verify(three).varargsObject(eq(10), eq("first arg"), startsWith("second"));
+
+        verifyNoMoreInteractions(one, two, three);
+
+        try {
+            verify(three).varargsObject(eq(10), eq("first arg"), startsWith("third"));
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/CleaningUpPotentialStubbingTest.java b/src/test/java/org/mockitousage/misuse/CleaningUpPotentialStubbingTest.java
new file mode 100644
index 0000000..30d1e57
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/CleaningUpPotentialStubbingTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.misuse;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class CleaningUpPotentialStubbingTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Test
+    public void shouldResetOngoingStubbingOnVerify() {
+        // first test
+        mock.booleanReturningMethod();
+        verify(mock).booleanReturningMethod();
+
+        // second test
+        assertOngoingStubbingIsReset();
+    }
+
+    @Test
+    public void shouldResetOngoingStubbingOnInOrder() {
+        mock.booleanReturningMethod();
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).booleanReturningMethod();
+        assertOngoingStubbingIsReset();
+    }
+
+    @Test
+    public void shouldResetOngoingStubbingOnDoReturn() {
+        mock.booleanReturningMethod();
+        doReturn(false).when(mock).booleanReturningMethod();
+        assertOngoingStubbingIsReset();
+    }
+
+    private void assertOngoingStubbingIsReset() {
+        try {
+            //In real, there might be a call to real object or a final method call
+            //I'm modelling it with null
+            when(null).thenReturn("anything");
+            fail();
+        } catch (MissingMethodInvocationException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/DescriptiveMessagesOnMisuseTest.java b/src/test/java/org/mockitousage/misuse/DescriptiveMessagesOnMisuseTest.java
new file mode 100644
index 0000000..09f0034
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/DescriptiveMessagesOnMisuseTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.misuse;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.exceptions.misusing.NullInsteadOfMockException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+public class DescriptiveMessagesOnMisuseTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    class Foo {
+        public final String finalMethod() {
+            return null;
+        }
+    }
+
+    @SuppressWarnings("all")
+    @Test
+    public void tryDescriptiveMessagesOnMisuse() {
+        Foo foo = mock(Foo.class);
+
+//        when(foo.finalMethod()).thenReturn("foo");
+//        doReturn("foo").when(foo).finalMethod();
+//        verify(foo).finalMethod();
+
+//        doReturn("foo");
+//        doReturn("bar");
+
+//        verifyNoMoreInteractions();
+//        verifyNoMoreInteractions(null);
+//        verifyNoMoreInteractions("");
+//        verifyZeroInteractions();
+//        verifyZeroInteractions(null);
+//        verifyZeroInteractions("");
+//
+//        inOrder();
+//        inOrder(null);
+//        inOrder("test");
+//        InOrder inOrder = inOrder(mock(List.class));
+//        inOrder.verify(mock).simpleMethod();
+
+//        verify(null);
+//        verify(mock.booleanReturningMethod());
+
+//        verify(mock).varargs("test", anyString());
+
+//        when("x").thenReturn("x");
+
+//        when(mock.simpleMethod());
+//        when(mock.differentMethod()).thenReturn("");
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldScreamWhenWholeMethodPassedToVerify() {
+        verify(mock.booleanReturningMethod());
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldScreamWhenWholeMethodPassedToVerifyNoMoreInteractions() {
+        verifyNoMoreInteractions(mock.byteReturningMethod());
+    }
+
+    @Test(expected=NotAMockException.class)
+    public void shouldScreamWhenInOrderCreatedWithDodgyMock() {
+        inOrder("not a mock");
+    }
+
+    @Test(expected=NullInsteadOfMockException.class)
+    public void shouldScreamWhenInOrderCreatedWithNulls() {
+        inOrder(mock, null);
+    }
+
+    @Test(expected=NullInsteadOfMockException.class)
+    public void shouldScreamNullPassedToVerify() {
+        verify(null);
+    }
+
+    @Test(expected=NullInsteadOfMockException.class)
+    public void shouldScreamWhenNotMockPassedToVerifyNoMoreInteractions() {
+        verifyNoMoreInteractions(null, "blah");
+    }
+
+    @SuppressWarnings("all")
+    @Test(expected=MockitoException.class)
+    public void shouldScreamWhenNullPassedToVerifyNoMoreInteractions() {
+        verifyNoMoreInteractions((Object[])null);
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/DetectingFinalMethodsTest.java b/src/test/java/org/mockitousage/misuse/DetectingFinalMethodsTest.java
new file mode 100644
index 0000000..4468ee0
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/DetectingFinalMethodsTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.misuse;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.*;
+
+public class DetectingFinalMethodsTest extends TestBase {
+
+    class WithFinal {
+        final int foo() {
+            return 0;
+        }
+    }
+
+    @Mock private WithFinal withFinal;
+
+    @Test
+    public void shouldFailWithUnfinishedVerification() {
+        assumeTrue("Does not apply for inline mocks", withFinal.getClass() != WithFinal.class);
+        verify(withFinal).foo();
+        try {
+            verify(withFinal).foo();
+            fail();
+        } catch (UnfinishedVerificationException e) {}
+    }
+
+    @Test
+    public void shouldFailWithUnfinishedStubbing() {
+        assumeTrue("Does not apply for inline mocks", withFinal.getClass() != WithFinal.class);
+        withFinal = mock(WithFinal.class);
+        try {
+            when(withFinal.foo()).thenReturn(null);
+            fail();
+        } catch (MissingMethodInvocationException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/DetectingMisusedMatchersTest.java b/src/test/java/org/mockitousage/misuse/DetectingMisusedMatchersTest.java
new file mode 100644
index 0000000..893ef6d
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/DetectingMisusedMatchersTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.misuse;
+
+import java.util.Observer;
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyObject;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.verify;
+
+public class DetectingMisusedMatchersTest extends TestBase {
+
+    class WithFinal {
+        final Object finalMethod(Object object) {
+            return null;
+        }
+    }
+
+    @Mock private WithFinal withFinal;
+
+    @After
+    public void resetState() {
+        super.resetState();
+    }
+
+    private void misplaced_anyObject_argument_matcher() {
+        anyObject();
+    }
+
+    private void misplaced_anyInt_argument_matcher() {
+        anyInt();
+    }
+
+    private void misplaced_anyBoolean_argument_matcher() {
+        anyBoolean();
+    }
+
+    @Test
+    public void should_fail_fast_when_argument_matchers_are_abused() {
+        misplaced_anyObject_argument_matcher();
+        try {
+            mock(IMethods.class);
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e).hasMessageContaining("Misplaced or misused argument matcher");
+        }
+    }
+
+    @Test
+    public void should_report_argument_locations_when_argument_matchers_misused() {
+        try {
+            Observer observer = mock(Observer.class);
+
+            misplaced_anyInt_argument_matcher();
+            misplaced_anyObject_argument_matcher();
+            misplaced_anyBoolean_argument_matcher();
+
+            observer.update(null, null);
+
+            validateMockitoUsage();
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e)
+                .hasMessageContaining("DetectingMisusedMatchersTest.misplaced_anyInt_argument_matcher")
+                .hasMessageContaining("DetectingMisusedMatchersTest.misplaced_anyObject_argument_matcher")
+                .hasMessageContaining("DetectingMisusedMatchersTest.misplaced_anyBoolean_argument_matcher");
+        }
+    }
+
+
+    @Test
+    public void shouldSayUnfinishedVerificationButNotInvalidUseOfMatchers() {
+        assumeTrue("Does not apply for inline mocks", withFinal.getClass() != WithFinal.class);
+        verify(withFinal).finalMethod(anyObject());
+        try {
+            verify(withFinal);
+            fail();
+        } catch (UnfinishedVerificationException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/ExplicitFrameworkValidationTest.java b/src/test/java/org/mockitousage/misuse/ExplicitFrameworkValidationTest.java
new file mode 100644
index 0000000..f48f8b9
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/ExplicitFrameworkValidationTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.misuse;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ExplicitFrameworkValidationTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @Test
+    public void shouldValidateExplicitly() {
+        verify(mock);
+        try {
+            Mockito.validateMockitoUsage();
+            fail();
+        } catch (UnfinishedVerificationException e) {}
+    }
+
+    @Test
+    public void shouldDetectUnfinishedStubbing() {
+        when(mock.simpleMethod());
+        try {
+            Mockito.validateMockitoUsage();
+            fail();
+        } catch (UnfinishedStubbingException e) {}
+    }
+
+    @Test
+    public void shouldDetectMisplacedArgumentMatcher() {
+        anyObject();
+        try {
+            Mockito.validateMockitoUsage();
+            fail();
+        } catch (InvalidUseOfMatchersException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/InvalidUsageTest.java b/src/test/java/org/mockitousage/misuse/InvalidUsageTest.java
new file mode 100644
index 0000000..1ba6e99
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/InvalidUsageTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.misuse;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.Mockito.*;
+
+public class InvalidUsageTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private IMethods mockTwo;
+
+    @After
+    public void resetState() {
+        super.resetState();
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldRequireArgumentsWhenVerifyingNoMoreInteractions() {
+        verifyNoMoreInteractions();
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldRequireArgumentsWhenVerifyingZeroInteractions() {
+        verifyZeroInteractions();
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotCreateInOrderObjectWithoutMocks() {
+        inOrder();
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowVerifyingInOrderUnfamilarMocks() {
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mockTwo).simpleMethod();
+    }
+
+    @Test(expected=MissingMethodInvocationException.class)
+    public void shouldReportMissingMethodInvocationWhenStubbing() {
+        when(mock.simpleMethod()).thenReturn("this stubbing is required to make sure Stubbable is pulled");
+        when("".toString()).thenReturn("x");
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowSettingInvalidCheckedException() throws Exception {
+        when(mock.simpleMethod()).thenThrow(new Exception());
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowSettingNullThrowable() throws Exception {
+        when(mock.simpleMethod()).thenThrow(new Throwable[] {null});
+    }
+
+    @SuppressWarnings("all")
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowSettingNullThrowableVararg() throws Exception {
+        when(mock.simpleMethod()).thenThrow((Throwable) null);
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowSettingNullConsecutiveThrowable() throws Exception {
+        when(mock.simpleMethod()).thenThrow(new RuntimeException(), null);
+    }
+
+    final class FinalClass {}
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowMockingFinalClassesIfDisabled() throws Exception {
+        assumeFalse("Inlining mock allows mocking final classes", mock(FinalClass.class).getClass() == FinalClass.class);
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldNotAllowMockingPrimitves() throws Exception {
+        mock(Integer.TYPE);
+    }
+
+    interface ObjectLikeInterface {
+        boolean equals(Object o);
+        String toString();
+        int hashCode();
+    }
+
+    @Test
+    public void shouldNotMockObjectMethodsOnInterface() throws Exception {
+        ObjectLikeInterface inter = mock(ObjectLikeInterface.class);
+
+        inter.equals(null);
+        inter.toString();
+        inter.hashCode();
+
+        verifyZeroInteractions(inter);
+    }
+
+    public void shouldNotMockObjectMethodsOnClass() throws Exception {
+        Object clazz = mock(ObjectLikeInterface.class);
+
+        clazz.equals(null);
+        clazz.toString();
+        clazz.hashCode();
+
+        verifyZeroInteractions(clazz);
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/RestrictedObjectMethodsTest.java b/src/test/java/org/mockitousage/misuse/RestrictedObjectMethodsTest.java
new file mode 100644
index 0000000..59be28d
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/RestrictedObjectMethodsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.misuse;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.verify;
+
+public class RestrictedObjectMethodsTest extends TestBase {
+
+    @Mock List<?> mock;
+
+    @After
+    public void after() {
+        this.resetState();
+    }
+
+    @Test
+    public void shouldScreamWhenVerifyToString() {
+        try {
+            verify(mock).toString();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("cannot verify");
+        }
+    }
+
+    @Test
+    public void shouldBeSilentWhenVerifyHashCode() {
+        //because it leads to really wierd behavior sometimes
+        //it's because cglib & my code can occasionelly call those methods
+        // and when user has verification started at that time there will be a mess
+        verify(mock).hashCode();
+    }
+
+    @Test
+    public void shouldBeSilentWhenVerifyEquals() {
+        //because it leads to really wierd behavior sometimes
+        //it's because cglib & my code can occasionelly call those methods
+        // and when user has verification started at that time there will be a mess
+        verify(mock).equals(null);
+    }
+
+    @Test
+    public void shouldBeSilentWhenVerifyEqualsInOrder() {
+        //because it leads to really wierd behavior sometimes
+        //it's because cglib & my code can occasionelly call those methods
+        // and when user has verification started at that time there will be a mess
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).equals(null);
+    }
+}
diff --git a/src/test/java/org/mockitousage/misuse/SpyStubbingMisuseTest.java b/src/test/java/org/mockitousage/misuse/SpyStubbingMisuseTest.java
new file mode 100644
index 0000000..a36c66a
--- /dev/null
+++ b/src/test/java/org/mockitousage/misuse/SpyStubbingMisuseTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.misuse;
+
+import org.junit.Test;
+import org.mockito.exceptions.misusing.WrongTypeOfReturnValue;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.*;
+
+public class SpyStubbingMisuseTest {
+
+    @Test
+    public void nestedWhenTest() {
+        Strategy mfoo = mock(Strategy.class);
+        Sampler mpoo = mock(Sampler.class);
+        Producer out = spy(new Producer(mfoo));
+
+        try {
+            when(out.produce()).thenReturn(mpoo);
+            fail();
+        } catch (WrongTypeOfReturnValue e) {
+            assertThat(e.getMessage()).contains("spy").contains("syntax").contains("doReturn|Throw");
+        }
+    }
+
+    public class Sample { }
+
+    public class Strategy {
+        Sample getSample() {
+            return new Sample();
+        }
+    }
+
+    public class Sampler {
+        Sample sample;
+        Sampler(Strategy f) {
+            sample = f.getSample();
+        }
+    }
+
+    public class Producer {
+        Strategy strategy;
+        Producer(Strategy f) {
+            strategy = f;
+        }
+        Sampler produce() {
+            return new Sampler(strategy);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/package-info.java b/src/test/java/org/mockitousage/package-info.java
new file mode 100644
index 0000000..bcc8078
--- /dev/null
+++ b/src/test/java/org/mockitousage/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Functional tests (should not be in {@link org.mockito} package because of stack trace filtering)
+ *
+ * {@link org.mockito} is for unit tests
+ */
+package org.mockitousage;
diff --git a/src/test/java/org/mockitousage/packageprotected/MockingPackageProtectedTest.java b/src/test/java/org/mockitousage/packageprotected/MockingPackageProtectedTest.java
new file mode 100644
index 0000000..b06d073
--- /dev/null
+++ b/src/test/java/org/mockitousage/packageprotected/MockingPackageProtectedTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.packageprotected;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.mock;
+
+public class MockingPackageProtectedTest extends TestBase {
+
+    static class Foo {}
+
+    class Bar {}
+
+    @Test
+    public void shouldMockPackageProtectedClasses() {
+        mock(PackageProtected.class);
+        mock(Foo.class);
+        mock(Bar.class);
+    }
+}
diff --git a/src/test/java/org/mockitousage/packageprotected/PackageProtected.java b/src/test/java/org/mockitousage/packageprotected/PackageProtected.java
new file mode 100644
index 0000000..0c1ed91
--- /dev/null
+++ b/src/test/java/org/mockitousage/packageprotected/PackageProtected.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.packageprotected;
+
+class PackageProtected {
+
+}
diff --git a/src/test/java/org/mockitousage/performance/LoadsOfMocksTest.java b/src/test/java/org/mockitousage/performance/LoadsOfMocksTest.java
new file mode 100644
index 0000000..730c801
--- /dev/null
+++ b/src/test/java/org/mockitousage/performance/LoadsOfMocksTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.performance;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+public class LoadsOfMocksTest extends TestBase {
+
+    @Ignore("Use it for performance checks")
+    @Test
+    public void testSomething() {
+        List<IMethods> mocks = new LinkedList<IMethods>();
+        for (int i = 0; i < 50000; i++) {
+            System.out.println("Mock no: " + i);
+            IMethods mock = mock(IMethods.class);
+            mocks.add(mock);
+
+            when(mock.simpleMethod(1)).thenReturn("one");
+            when(mock.simpleMethod(2)).thenReturn("two");
+
+            assertEquals("one", mock.simpleMethod(1));
+            assertEquals("two", mock.simpleMethod(2));
+
+            verify(mock).simpleMethod(1);
+            verify(mock).simpleMethod(2);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/performance/StubOnlyAvoidMemoryConsumptionTest.java b/src/test/java/org/mockitousage/performance/StubOnlyAvoidMemoryConsumptionTest.java
new file mode 100644
index 0000000..d468e24
--- /dev/null
+++ b/src/test/java/org/mockitousage/performance/StubOnlyAvoidMemoryConsumptionTest.java
@@ -0,0 +1,30 @@
+package org.mockitousage.performance;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.mockito.Mockito.*;
+
+public class StubOnlyAvoidMemoryConsumptionTest {
+
+    @Test
+    public void using_stub_only_wont_thrown_an_OutOfMemoryError() {
+        Object obj = mock(Object.class, withSettings().stubOnly());
+        when(obj.toString()).thenReturn("asdf");
+
+        for (int i = 0; i < 1000000; i++) {
+            obj.toString();
+        }
+    }
+
+    @Test
+    @Ignore("ignored because it will detonate our test suite with an OOM for real")
+    public void without_stub_only_mocks_will_store_invocations_leading_to_an_OutOfMemoryError() {
+        Object obj = mock(Object.class, withSettings());
+        when(obj.toString()).thenReturn("asdf");
+
+        for (int i = 0; i < 1000000; i++) {
+            obj.toString();
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/puzzlers/BridgeMethodPuzzleTest.java b/src/test/java/org/mockitousage/puzzlers/BridgeMethodPuzzleTest.java
new file mode 100644
index 0000000..81f4fe7
--- /dev/null
+++ b/src/test/java/org/mockitousage/puzzlers/BridgeMethodPuzzleTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.puzzlers;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockitoutil.Conditions.bridgeMethod;
+
+/**
+ * Bridge method is generated by compiler when erasure in parent class is
+ * different. When is different then it means that in runtime we will have
+ * overloading rather than overridding Therefore the compiler generates bridge
+ * method in Subclass so that erasures are the same, signatures of methods match
+ * and overridding is ON.
+ */
+@SuppressWarnings("unchecked")
+public class BridgeMethodPuzzleTest extends TestBase {
+
+    private class Super<T> {
+        public String say(T t) {
+            return "Super says: " + t;
+        }
+    }
+
+    private class Sub extends Super<String> {
+        @Override
+        public String say(String t)  {
+            return "Dummy says: " + t;
+        }
+    }
+
+    @Test
+    public void shouldHaveBridgeMethod() throws Exception {
+        Super s = new Sub();
+
+        assertEquals("Dummy says: Hello", s.say("Hello"));
+
+        Assertions.assertThat(Sub.class).has(bridgeMethod("say"));
+        Assertions.assertThat(s).has(bridgeMethod("say"));
+    }
+
+    @Test
+    public void shouldVerifyCorrectlyWhenBridgeMethodCalled() throws Exception {
+        //Super has following erasure: say(Object) which differs from Dummy.say(String)
+        //mock has to detect it and do the super.say()
+        Sub s = mock(Sub.class);
+        Super<String> s_down = s;
+        s_down.say("Hello");
+
+        verify(s).say("Hello");
+    }
+
+    @Test
+    public void shouldVerifyCorrectlyWhenBridgeMethodVerified() throws Exception {
+        //Super has following erasure: say(Object) which differs from Dummy.say(String)
+        //mock has to detect it and do the super.say()
+        Sub s = mock(Sub.class);
+        Super<String> s_down = s;
+        s.say("Hello");
+
+        verify(s_down).say("Hello");
+    }
+}
diff --git a/src/test/java/org/mockitousage/puzzlers/OverloadingPuzzleTest.java b/src/test/java/org/mockitousage/puzzlers/OverloadingPuzzleTest.java
new file mode 100644
index 0000000..b41e0b5
--- /dev/null
+++ b/src/test/java/org/mockitousage/puzzlers/OverloadingPuzzleTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.puzzlers;
+
+import org.junit.Test;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class OverloadingPuzzleTest extends TestBase {
+
+    private Super mock;
+
+    private void setMockWithDowncast(Super mock) {
+        this.mock = mock;
+    }
+
+    private interface Super {
+        void say(Object message);
+    }
+
+    private interface Sub extends Super {
+        void say(String message);
+    }
+
+    private void say(Object message) {
+        mock.say(message);
+    }
+
+    @Test
+    public void shouldUseArgumentTypeWhenOverloadingPuzzleDetected() throws Exception {
+        Sub sub = mock(Sub.class);
+        setMockWithDowncast(sub);
+        say("Hello");
+        try {
+            verify(sub).say("Hello");
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/serialization/AcrossClassLoaderSerializationTest.java b/src/test/java/org/mockitousage/serialization/AcrossClassLoaderSerializationTest.java
new file mode 100644
index 0000000..3c6601b
--- /dev/null
+++ b/src/test/java/org/mockitousage/serialization/AcrossClassLoaderSerializationTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.serialization;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.mock.SerializableMode;
+import org.mockitousage.IMethods;
+import org.mockitoutil.SimplePerRealmReloadingClassLoader;
+import org.mockitoutil.SimpleSerializationUtil;
+
+import java.io.ByteArrayInputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+
+public class AcrossClassLoaderSerializationTest {
+
+    public IMethods mock;
+
+    @Before
+    public void reproduce_CCE_by_creating_a_mock_with_IMethods_before() throws Exception {
+        mock = Mockito.mock(IMethods.class);
+    }
+
+    @Test
+    public void check_that_mock_can_be_serialized_in_a_classloader_and_deserialized_in_another() throws Exception {
+        byte[] bytes = create_mock_and_serialize_it_in_class_loader_A();
+
+        Object the_deserialized_mock = read_stream_and_deserialize_it_in_class_loader_B(bytes);
+    }
+
+    private Object read_stream_and_deserialize_it_in_class_loader_B(byte[] bytes) throws Exception {
+        return new SimplePerRealmReloadingClassLoader(this.getClass().getClassLoader(), isolating_test_classes())
+                .doInRealm(
+                        "org.mockitousage.serialization.AcrossClassLoaderSerializationTest$ReadStreamAndDeserializeIt",
+                        new Class<?>[]{ byte[].class },
+                        new Object[]{ bytes }
+                );
+    }
+
+    private byte[] create_mock_and_serialize_it_in_class_loader_A() throws Exception {
+        return (byte[]) new SimplePerRealmReloadingClassLoader(this.getClass().getClassLoader(), isolating_test_classes())
+                .doInRealm("org.mockitousage.serialization.AcrossClassLoaderSerializationTest$CreateMockAndSerializeIt");
+    }
+
+
+    private SimplePerRealmReloadingClassLoader.ReloadClassPredicate isolating_test_classes() {
+        return new SimplePerRealmReloadingClassLoader.ReloadClassPredicate() {
+            public boolean acceptReloadOf(String qualifiedName) {
+                return qualifiedName.contains("org.mockitousage")
+                        || qualifiedName.contains("org.mockitoutil")
+                        ;
+            }
+        };
+    }
+
+
+    // see create_mock_and_serialize_it_in_class_loader_A
+    public static class CreateMockAndSerializeIt implements Callable<byte[]> {
+        public byte[] call() throws Exception {
+            AClassToBeMockedInThisTestOnlyAndInCallablesOnly mock = Mockito.mock(
+                    AClassToBeMockedInThisTestOnlyAndInCallablesOnly.class,
+                    Mockito.withSettings().serializable(SerializableMode.ACROSS_CLASSLOADERS)
+            );
+            // use MethodProxy before
+            mock.returningSomething();
+
+            return SimpleSerializationUtil.serializeMock(mock).toByteArray();
+        }
+    }
+
+    // see read_stream_and_deserialize_it_in_class_loader_B
+    public static class ReadStreamAndDeserializeIt implements Callable<Object> {
+        private byte[] bytes;
+
+        public ReadStreamAndDeserializeIt(byte[] bytes) {
+            this.bytes = bytes;
+        }
+
+        public Object call() throws Exception {
+            ByteArrayInputStream to_unserialize = new ByteArrayInputStream(bytes);
+            return SimpleSerializationUtil.deserializeMock(
+                    to_unserialize,
+                    AClassToBeMockedInThisTestOnlyAndInCallablesOnly.class
+            );
+        }
+    }
+
+
+    public static class AClassToBeMockedInThisTestOnlyAndInCallablesOnly {
+        List returningSomething() { return Collections.emptyList(); }
+    }
+}
diff --git a/src/test/java/org/mockitousage/serialization/DeepStubsSerializableTest.java b/src/test/java/org/mockitousage/serialization/DeepStubsSerializableTest.java
new file mode 100644
index 0000000..7027d4c
--- /dev/null
+++ b/src/test/java/org/mockitousage/serialization/DeepStubsSerializableTest.java
@@ -0,0 +1,85 @@
+package org.mockitousage.serialization;
+
+import org.junit.Test;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+import static org.mockitoutil.SimpleSerializationUtil.serializeAndBack;
+
+public class DeepStubsSerializableTest {
+
+    @Test
+    public void should_serialize_and_deserialize_mock_created_with_deep_stubs() throws Exception {
+        // given
+        SampleClass sampleClass = mock(SampleClass.class, withSettings().defaultAnswer(RETURNS_DEEP_STUBS).serializable());
+        when(sampleClass.getSample().isFalse()).thenReturn(true);
+        when(sampleClass.getSample().number()).thenReturn(999);
+
+        // when
+        SampleClass deserializedSample = serializeAndBack(sampleClass);
+
+        // then
+        assertThat(deserializedSample.getSample().isFalse()).isEqualTo(true);
+        assertThat(deserializedSample.getSample().number()).isEqualTo(999);
+    }
+
+    @Test
+    public void should_serialize_and_deserialize_parameterized_class_mocked_with_deep_stubs() throws Exception {
+        // given
+        ListContainer deep_stubbed = mock(ListContainer.class, withSettings().defaultAnswer(RETURNS_DEEP_STUBS).serializable());
+        when(deep_stubbed.iterator().next().add("yes")).thenReturn(true);
+
+        // when
+        ListContainer deserialized_deep_stub = serializeAndBack(deep_stubbed);
+
+        // then
+        assertThat(deserialized_deep_stub.iterator().next().add("not stubbed but mock already previously resolved")).isEqualTo(false);
+        assertThat(deserialized_deep_stub.iterator().next().add("yes")).isEqualTo(true);
+    }
+
+    @Test(expected = ClassCastException.class)
+    public void should_discard_generics_metadata_when_serialized_then_disabling_deep_stubs_with_generics() throws Exception {
+        // given
+        ListContainer deep_stubbed = mock(ListContainer.class, withSettings().defaultAnswer(RETURNS_DEEP_STUBS).serializable());
+        when(deep_stubbed.iterator().hasNext()).thenReturn(true);
+
+        ListContainer deserialized_deep_stub = serializeAndBack(deep_stubbed);
+
+        // when stubbing on a deserialized mock
+        when(deserialized_deep_stub.iterator().next().get(42)).thenReturn("no");
+
+        // then revert to the default RETURNS_DEEP_STUBS and the code will raise a ClassCastException
+    }
+
+
+    static class SampleClass implements Serializable {
+        SampleClass2 getSample() { return new SampleClass2(); }
+    }
+
+    static class SampleClass2 implements Serializable {
+        boolean isFalse() { return false; }
+        int number() { return 100; }
+    }
+
+    static class Container<E> implements Iterable<E>, Serializable {
+        private E e;
+        public Container(E e) { this.e = e; }
+        public E get() { return e; }
+
+        public Iterator<E> iterator() {
+            return new Iterator<E>() {
+                public boolean hasNext() { return true; }
+                public E next() { return e; }
+                public void remove() { }
+            };
+        }
+    }
+
+    static class ListContainer extends Container<List<String>> {
+        public ListContainer(List<String> list) { super(list); }
+    }
+}
diff --git a/src/test/java/org/mockitousage/serialization/ParallelSerializationTest.java b/src/test/java/org/mockitousage/serialization/ParallelSerializationTest.java
new file mode 100644
index 0000000..92faeed
--- /dev/null
+++ b/src/test/java/org/mockitousage/serialization/ParallelSerializationTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.serialization;
+
+import org.junit.Test;
+import org.mockitousage.IMethods;
+import org.mockitoutil.SimpleSerializationUtil;
+
+import java.nio.charset.CharacterCodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.*;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+public class ParallelSerializationTest {
+
+    @Test
+    public void single_mock_being_serialized_in_different_classloaders_by_multiple_threads() throws ExecutionException, InterruptedException {
+        // given
+        int iterations = 2;
+        int threadingFactor = 200;
+        final ExecutorService executorService = Executors.newFixedThreadPool(threadingFactor);
+        final IMethods iMethods_that_store_invocations = mock(IMethods.class, withSettings().serializable());
+
+        // when
+        for (int i = 0; i <= iterations; i++) {
+            List<Future<?>> futures = new ArrayList<Future<?>>(threadingFactor);
+            final CyclicBarrier barrier_that_will_wait_until_threads_are_ready = new CyclicBarrier(threadingFactor);
+
+            // prepare all threads by submitting a callable
+            //  - that will serialize the mock a 'threadingFactor' times
+            //  - that will use the mock a 'threadingFactor' times
+            for (int j = 0; j < threadingFactor; j++) {
+                // submit a callable that will serialize the mock 'iMethods'
+                futures.add(executorService.submit(new Callable<Object>() {
+                    public Object call() throws Exception {
+                        barrier_that_will_wait_until_threads_are_ready.await();
+
+                        randomCallOn(iMethods_that_store_invocations);
+
+                        return SimpleSerializationUtil.serializeMock(iMethods_that_store_invocations).toByteArray();
+                    }
+                }));
+
+                // submit a callable that will only use the mock 'iMethods'
+                executorService.submit(new Callable<Object>() {
+                    public Object call() throws Exception {
+                        barrier_that_will_wait_until_threads_are_ready.await();
+                        return iMethods_that_store_invocations.longObjectReturningMethod();
+                    }
+                });
+            }
+
+            // ensure we are getting the futures
+            for (Future<?> future : futures) {
+                future.get();
+            }
+        }
+    }
+
+    private void randomCallOn(IMethods iMethods) throws CharacterCodingException {
+        int random = new Random().nextInt(10);
+        switch (random) {
+            case 0 : iMethods.arrayReturningMethod(); break;
+            case 1 : iMethods.longObjectReturningMethod(); break;
+            case 2 : iMethods.linkedListReturningMethod(); break;
+            case 3 : iMethods.iMethodsReturningMethod(); break;
+            case 4 : iMethods.canThrowException(); break;
+            case 5 : iMethods.differentMethod(); break;
+            case 6 : iMethods.voidMethod(); break;
+            case 7 : iMethods.varargsString(1, ""); break;
+            case 8 : iMethods.forMap(null); break;
+            case 9 : iMethods.throwsNothing(false); break;
+            default:
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/session/MockitoSessionTest.java b/src/test/java/org/mockitousage/session/MockitoSessionTest.java
new file mode 100644
index 0000000..8debb94
--- /dev/null
+++ b/src/test/java/org/mockitousage/session/MockitoSessionTest.java
@@ -0,0 +1,138 @@
+package org.mockitousage.session;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.quality.Strictness;
+import org.mockitousage.IMethods;
+import org.mockitoutil.JUnitResultAssert;
+
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+public class MockitoSessionTest {
+
+    private JUnitCore junit = new JUnitCore();
+
+    @Test public void session_without_any_configuration() {
+        //when
+        Result result = junit.run(MockitoSessionTest.SessionWithoutAnyConfiguration.class);
+
+        //expect
+        JUnitResultAssert.assertThat(result).succeeds(1);
+    }
+
+    @Test public void session_without_init_mocks_configured() {
+        //when
+        Result result = junit.run(MockitoSessionTest.SessionWithoutInitMocksConfigured.class);
+
+        //expect
+        JUnitResultAssert.assertThat(result).succeeds(1);
+    }
+
+    @Test public void session_without_strictness_configured() {
+        //when
+        Result result = junit.run(MockitoSessionTest.SessionWithoutStrictnessConfigured.class);
+
+        //expect
+        JUnitResultAssert.assertThat(result).succeeds(1);
+    }
+
+    @Test public void session_with_incorrect_mockito_usage() {
+        //when
+        Result result = junit.run(MockitoSessionTest.SessionWithIncorrectMockitoUsage.class);
+
+        //expect
+        JUnitResultAssert.assertThat(result).fails(1, UnfinishedStubbingException.class);
+    }
+
+    @Test public void reports_other_failure_and_incorrect_mockito_usage() {
+        //when
+        Result result = junit.run(MockitoSessionTest.SessionWithTestFailureAndIncorrectMockitoUsage.class);
+
+        //expect
+        JUnitResultAssert.assertThat(result)
+                .failsExactly(AssertionError.class, UnfinishedStubbingException.class);
+    }
+
+    public static class SessionWithoutAnyConfiguration {
+
+        @Mock IMethods mock;
+
+        //session without initMocks is not currently supported
+        MockitoSession mockito = Mockito.mockitoSession().startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void some_test() {
+            assertNull(mock); //initMocks() was not used when configuring session
+        }
+    }
+
+    public static class SessionWithoutInitMocksConfigured {
+
+        @Mock IMethods mock;
+
+        MockitoSession mockito = Mockito.mockitoSession().strictness(Strictness.LENIENT).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void some_test() {
+            assertNull(mock); //initMocks() was not used when configuring session
+        }
+    }
+
+    public static class SessionWithoutStrictnessConfigured {
+        @Mock IMethods mock;
+
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void some_test() {
+            assertNotNull(mock);
+        }
+    }
+
+    public static class SessionWithIncorrectMockitoUsage {
+        @Mock IMethods mock;
+
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void unfinished_stubbing() {
+            when(mock.simpleMethod());
+        }
+    }
+
+    public static class SessionWithTestFailureAndIncorrectMockitoUsage {
+        @Mock IMethods mock;
+
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void unfinished_stubbing_with_other_failure() {
+            when(mock.simpleMethod());
+            assertTrue(false);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/spies/PartialMockingWithSpiesTest.java b/src/test/java/org/mockitousage/spies/PartialMockingWithSpiesTest.java
new file mode 100644
index 0000000..0f35529
--- /dev/null
+++ b/src/test/java/org/mockitousage/spies/PartialMockingWithSpiesTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.spies;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockitoutil.Conditions.methodsInStackTrace;
+
+@SuppressWarnings("unchecked")
+public class PartialMockingWithSpiesTest extends TestBase {
+
+    @Before
+    public void pleaseMakeStackTracesClean() {
+        makeStackTracesClean();
+    }
+
+    class InheritMe {
+        private String inherited = "100$";
+        protected String getInherited() {
+            return inherited;
+        }
+    }
+
+    class Person extends InheritMe {
+        private final Name defaultName = new Name("Default name");
+
+        public String getName() {
+            return guessName().name;
+        }
+
+        Name guessName() {
+            return defaultName;
+        }
+
+        public String howMuchDidYouInherit() {
+            return getInherited();
+        }
+
+        public String getNameButDelegateToMethodThatThrows() {
+            throwSomeException();
+            return guessName().name;
+        }
+
+        private void throwSomeException() {
+            throw new RuntimeException("boo");
+        }
+    }
+
+    class Name {
+        private final String name;
+
+        public Name(String name) {
+            this.name = name;
+        }
+    }
+
+    Person spy = spy(new Person());
+
+    @Test
+    public void shouldCallRealMethdsEvenDelegatedToOtherSelfMethod() {
+        // when
+        String name = spy.getName();
+
+        // then
+        assertEquals("Default name", name);
+    }
+
+    @Test
+    public void shouldAllowStubbingOfMethodsThatDelegateToOtherMethods() {
+        // when
+        when(spy.getName()).thenReturn("foo");
+
+        // then
+        assertEquals("foo", spy.getName());
+    }
+
+    @Test
+    public void shouldAllowStubbingWithThrowablesMethodsThatDelegateToOtherMethods() {
+        // when
+        doThrow(new RuntimeException("appetite for destruction"))
+            .when(spy).getNameButDelegateToMethodThatThrows();
+
+        // then
+        try {
+            spy.getNameButDelegateToMethodThatThrows();
+            fail();
+        } catch(Exception e) {
+            assertEquals("appetite for destruction", e.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldStackTraceGetFilteredOnUserExceptions() {
+        try {
+            // when
+            spy.getNameButDelegateToMethodThatThrows();
+            fail();
+        } catch (Throwable t) {
+            // then
+            Assertions.assertThat(t).has(methodsInStackTrace(
+                    "throwSomeException",
+                    "getNameButDelegateToMethodThatThrows",
+                    "shouldStackTraceGetFilteredOnUserExceptions"
+                    ));
+        }
+    }
+
+//    @Test //manual verification
+    public void verifyTheStackTrace() {
+        spy.getNameButDelegateToMethodThatThrows();
+    }
+
+    @Test
+    public void shouldVerify() {
+        // when
+        spy.getName();
+
+        // then
+        verify(spy).guessName();
+    }
+
+    @Test
+    public void shouldStub() {
+        // given
+        when(spy.guessName()).thenReturn(new Name("John"));
+        // when
+        String name = spy.getName();
+        // then
+        assertEquals("John", name);
+    }
+
+    @Test
+    public void shouldDealWithPrivateFieldsOfSubclasses() {
+        assertEquals("100$", spy.howMuchDidYouInherit());
+    }
+}
diff --git a/src/test/java/org/mockitousage/spies/SpyingOnInterfacesTest.java b/src/test/java/org/mockitousage/spies/SpyingOnInterfacesTest.java
new file mode 100644
index 0000000..d9fb539
--- /dev/null
+++ b/src/test/java/org/mockitousage/spies/SpyingOnInterfacesTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.spies;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.ClassFileVersion;
+import net.bytebuddy.description.modifier.TypeManifestation;
+import net.bytebuddy.description.modifier.Visibility;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+import net.bytebuddy.implementation.FixedValue;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings({"unchecked"})
+public class SpyingOnInterfacesTest extends TestBase {
+
+    @Test
+    public void shouldFailFastWhenCallingRealMethodOnInterface() throws Exception {
+        List<?> list = mock(List.class);
+        try {
+            //when
+            when(list.get(0)).thenCallRealMethod();
+            //then
+            fail();
+        } catch (MockitoException e) {
+        }
+    }
+
+    @Test
+    public void shouldFailInRuntimeWhenCallingRealMethodOnInterface() throws Exception {
+        //given
+        List<Object> list = mock(List.class);
+        when(list.get(0)).thenAnswer(
+                new Answer<Object>() {
+                    public Object answer(InvocationOnMock invocation) throws Throwable {
+                        return invocation.callRealMethod();
+                    }
+                }
+        );
+        try {
+            //when
+            list.get(0);
+            //then
+            fail();
+        } catch (MockitoException e) {
+        }
+    }
+
+    @Test
+    public void shouldAllowDelegatingToDefaultMethod() throws Exception {
+        assumeTrue("Test can only be executed on Java 8 capable VMs", ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V8));
+
+        Class<?> type = new ByteBuddy()
+                .makeInterface()
+                .defineMethod("foo", String.class, Visibility.PUBLIC)
+                .intercept(FixedValue.value("bar"))
+                .make()
+                .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
+                .getLoaded();
+
+        Object object = mock(type);
+
+        //when
+        when(type.getMethod("foo").invoke(object)).thenCallRealMethod();
+        //then
+        Assertions.assertThat(type.getMethod("foo").invoke(object)).isEqualTo((Object) "bar");
+        type.getMethod("foo").invoke(verify(object));
+    }
+
+    @Test
+    public void shouldAllowSpyingOnDefaultMethod() throws Exception {
+        assumeTrue("Test can only be executed on Java 8 capable VMs", ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V8));
+
+        Class<?> iFace = new ByteBuddy()
+                .makeInterface()
+                .defineMethod("foo", String.class, Visibility.PUBLIC)
+                .intercept(FixedValue.value("bar"))
+                .make()
+                .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
+                .getLoaded();
+
+        Class<?> impl = new ByteBuddy()
+                .subclass(iFace)
+                .make()
+                .load(iFace.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
+                .getLoaded();
+
+        Object object = spy(impl.newInstance());
+
+        //when
+        Assertions.assertThat(impl.getMethod("foo").invoke(object)).isEqualTo((Object) "bar");
+        //then
+        impl.getMethod("foo").invoke(verify(object));
+    }
+}
diff --git a/src/test/java/org/mockitousage/spies/SpyingOnRealObjectsTest.java b/src/test/java/org/mockitousage/spies/SpyingOnRealObjectsTest.java
new file mode 100644
index 0000000..b656b0f
--- /dev/null
+++ b/src/test/java/org/mockitousage/spies/SpyingOnRealObjectsTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.spies;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockitoutil.TestBase;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.TestCase.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.*;
+
+public class SpyingOnRealObjectsTest extends TestBase {
+
+    List<String> list = new LinkedList<String>();
+    List<String> spy = Mockito.spy(list);
+
+    @Test
+    public void shouldVerify() {
+        spy.add("one");
+        spy.add("two");
+
+        assertEquals("one", spy.get(0));
+        assertEquals("two", spy.get(1));
+
+        verify(spy).add("one");
+        verify(spy).add("two");
+    }
+
+    @Test
+    public void shouldBeAbleToMockObjectBecauseWhyNot() {
+        spy(new Object());
+    }
+
+    @Test
+    public void shouldStub() {
+        spy.add("one");
+        when(spy.get(0))
+            .thenReturn("1")
+            .thenReturn("1 again");
+
+        assertEquals("1", spy.get(0));
+        assertEquals("1 again", spy.get(0));
+        assertEquals("one", spy.iterator().next());
+
+        assertEquals(1, spy.size());
+    }
+
+    @Test
+    public void shouldAllowOverridingStubs() {
+        when(spy.contains(anyObject())).thenReturn(true);
+        when(spy.contains("foo")).thenReturn(false);
+
+        assertTrue(spy.contains("bar"));
+        assertFalse(spy.contains("foo"));
+    }
+
+    @Test
+    public void shouldStubVoid() {
+        doNothing()
+        .doThrow(new RuntimeException())
+        .when(spy)
+        .clear();
+
+        spy.add("one");
+        spy.clear();
+        try {
+            spy.clear();
+            fail();
+        } catch (RuntimeException e) {}
+
+        assertEquals(1, spy.size());
+    }
+
+    @Test
+    public void shouldStubWithDoReturnAndVerify() {
+        doReturn("foo")
+        .doReturn("bar")
+        .when(spy).get(0);
+
+        assertEquals("foo", spy.get(0));
+        assertEquals("bar", spy.get(0));
+
+        verify(spy, times(2)).get(0);
+        verifyNoMoreInteractions(spy);
+    }
+
+    @Test
+    public void shouldVerifyInOrder() {
+        spy.add("one");
+        spy.add("two");
+
+        InOrder inOrder = inOrder(spy);
+        inOrder.verify(spy).add("one");
+        inOrder.verify(spy).add("two");
+
+        verifyNoMoreInteractions(spy);
+    }
+
+    @Test
+    public void shouldVerifyInOrderAndFail() {
+        spy.add("one");
+        spy.add("two");
+
+        InOrder inOrder = inOrder(spy);
+        inOrder.verify(spy).add("two");
+        try {
+            inOrder.verify(spy).add("one");
+            fail();
+        } catch (VerificationInOrderFailure f) {}
+    }
+
+    @Test
+    public void shouldVerifyNumberOfTimes() {
+        spy.add("one");
+        spy.add("one");
+
+        verify(spy, times(2)).add("one");
+        verifyNoMoreInteractions(spy);
+    }
+
+    @Test
+    public void shouldVerifyNumberOfTimesAndFail() {
+        spy.add("one");
+        spy.add("one");
+
+        try {
+            verify(spy, times(3)).add("one");
+            fail();
+        } catch (TooLittleActualInvocations e) {}
+    }
+
+    @Test
+    public void shouldVerifyNoMoreInteractionsAndFail() {
+        spy.add("one");
+        spy.add("two");
+
+        verify(spy).add("one");
+        try {
+            verifyNoMoreInteractions(spy);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldToString() {
+        spy.add("foo");
+        assertEquals("[foo]" , spy.toString());
+    }
+
+    interface Foo {
+        String print();
+    }
+
+    @Test
+    public void shouldAllowSpyingAnonymousClasses() {
+        //when
+        Foo spy = spy(new Foo() {
+            public String print() {
+                return "foo";
+            }
+        });
+
+        //then
+        assertEquals("foo", spy.print());
+    }
+
+    @Test
+    public void shouldSayNiceMessageWhenSpyingOnPrivateClass() throws Exception {
+        List<String> real = Arrays.asList("first", "second");
+        try {
+            List<String> spy = spy(real);
+            assumeTrue("Using inline mocks, it is possible to spy on private types", spy.getClass() != real.getClass());
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("Most likely it is due to mocking a private class that is not visible to Mockito");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/spies/StubbingSpiesDoesNotYieldNPETest.java b/src/test/java/org/mockitousage/spies/StubbingSpiesDoesNotYieldNPETest.java
new file mode 100644
index 0000000..12d3a41
--- /dev/null
+++ b/src/test/java/org/mockitousage/spies/StubbingSpiesDoesNotYieldNPETest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.spies;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+import java.util.Collection;
+import java.util.Map;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.spy;
+
+public class StubbingSpiesDoesNotYieldNPETest extends TestBase {
+
+    class Foo {
+        public int len(String text) {
+            return text.length();
+        }
+
+        public int size(Map<?, ?> map) {
+            return map.size();
+        }
+
+        public int size(Collection<?> collection) {
+            return collection.size();
+        }
+    }
+
+    @Test
+    public void shouldNotThrowNPE() throws Exception {
+        Foo foo = new Foo();
+        Foo spy = spy(foo);
+
+        spy.len(anyString());
+        spy.size(anyMap());
+        spy.size(anyList());
+        spy.size(anyCollection());
+        spy.size(anySet());
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/ClickableStackTracesTest.java b/src/test/java/org/mockitousage/stacktrace/ClickableStackTracesTest.java
new file mode 100644
index 0000000..e954c36
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/ClickableStackTracesTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class ClickableStackTracesTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    private void callMethodOnMock(String param) {
+        mock.simpleMethod(param);
+    }
+
+    private void verifyTheMock(int times, String param) {
+        verify(mock, times(times)).simpleMethod(param);
+    }
+
+    @Test
+    public void shouldShowActualAndExpectedWhenArgumentsAreDifferent() {
+        callMethodOnMock("foo");
+        try {
+            verifyTheMock(1, "not foo");
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e).hasMessageContaining("callMethodOnMock(").hasMessageContaining("verifyTheMock(");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/ClickableStackTracesWhenFrameworkMisusedTest.java b/src/test/java/org/mockitousage/stacktrace/ClickableStackTracesWhenFrameworkMisusedTest.java
new file mode 100644
index 0000000..c47b046
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/ClickableStackTracesWhenFrameworkMisusedTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class ClickableStackTracesWhenFrameworkMisusedTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @After
+    public void resetState() {
+        super.resetState();
+    }
+
+    private void misplacedArgumentMatcherHere() {
+        anyString();
+    }
+
+    @Test
+    public void shouldPointOutMisplacedMatcher() {
+        misplacedArgumentMatcherHere();
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (InvalidUseOfMatchersException e) {
+            assertThat(e)
+                .hasMessageContaining("-> at ")
+                .hasMessageContaining("misplacedArgumentMatcherHere(");
+        }
+    }
+
+    private void unfinishedStubbingHere() {
+        when(mock.simpleMethod());
+    }
+
+    @Test
+    public void shouldPointOutUnfinishedStubbing() {
+        unfinishedStubbingHere();
+
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (UnfinishedStubbingException e) {
+            assertThat(e)
+                .hasMessageContaining("-> at ")
+                .hasMessageContaining("unfinishedStubbingHere(");
+        }
+    }
+
+    @Test
+    public void shouldShowWhereIsUnfinishedVerification() throws Exception {
+        unfinishedVerificationHere();
+        try {
+            mock(IMethods.class);
+            fail();
+        } catch (UnfinishedVerificationException e) {
+            assertThat(e).hasMessageContaining("unfinishedVerificationHere(");
+        }
+    }
+
+    private void unfinishedVerificationHere() {
+        verify(mock);
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/ModellingDescriptiveMessagesTest.java b/src/test/java/org/mockitousage/stacktrace/ModellingDescriptiveMessagesTest.java
new file mode 100644
index 0000000..a09ee71
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/ModellingDescriptiveMessagesTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+@Ignore
+@RunWith(MockitoJUnitRunner.class)
+public class ModellingDescriptiveMessagesTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Before
+    public void cleanStackTrace() {
+        super.makeStackTracesClean();
+    }
+
+    @Test
+    public void makeSureStateIsValidatedInTheVeryFirstTestThanksToTheRunner() {
+        //mess up the state:
+        verify(mock);
+    }
+
+    @Test
+    public void shouldSayWantedButNotInvoked() {
+        verify(mock).otherMethod();
+    }
+
+    @Test
+    public void shouldPointOutInteractionsOnMockWhenOrdinaryVerificationFails() {
+        mock.otherMethod();
+        mock.booleanObjectReturningMethod();
+
+        verify(mock).simpleMethod();
+    }
+
+    @Test
+    public void shouldShowActualAndExpected() {
+        mock.simpleMethod("blah");
+        verify(mock).simpleMethod();
+    }
+
+    @Test
+    public void shouldSayTooLittleInvocations() {
+        mock.simpleMethod();
+        verify(mock, times(2)).simpleMethod();
+    }
+
+    @Test
+    public void shouldSayTooManyInvocations() {
+        mock.simpleMethod();
+        mock.simpleMethod();
+        verify(mock, times(1)).simpleMethod();
+    }
+
+    @Test
+    public void shouldSayWantedButNotInvokedInOrder() {
+        mock.simpleMethod();
+        mock.otherMethod();
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).otherMethod();
+        inOrder.verify(mock).simpleMethod();
+    }
+
+    @Test
+    public void shouldSayTooLittleInvocationsInOrder() {
+        mock.simpleMethod();
+        mock.otherMethod();
+        mock.otherMethod();
+
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).simpleMethod();
+        inOrder.verify(mock, times(3)).otherMethod();
+    }
+
+    @Test
+    public void shouldSayTooManyInvocationsInOrder() {
+        mock.otherMethod();
+        mock.otherMethod();
+
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock, times(1)).otherMethod();
+    }
+
+    @Test
+    public void shouldSayNeverWantedButInvokedHere() {
+        mock.otherMethod();
+
+        verify(mock, never()).otherMethod();
+    }
+
+    @Test
+    public void shouldSayTooLittleInvocationsInAtLeastModeInOrder() {
+        mock.simpleMethod();
+
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock, atLeast(2)).simpleMethod();
+    }
+
+    @Test
+    public void shouldSayTooLittleInvocationsInAtLeastMode() {
+        mock.simpleMethod();
+
+        verify(mock, atLeast(2)).simpleMethod();
+    }
+
+    @Test
+    public void shouldSayNoMoreInteractions() {
+        mock.simpleMethod();
+
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldSayUnstubbedMethodWasInvokedHere() {
+        mock = mock(IMethods.class, RETURNS_SMART_NULLS);
+
+        IMethods m = mock.iMethodsReturningMethod();
+
+        m.simpleMethod();
+    }
+
+    @Test
+    public void shouldPointOutUnfinishedStubbing() {
+        when(mock.simpleMethod());
+
+        verify(mock).simpleMethod();
+    }
+
+    @Test
+    public void shouldMentionFinalAndObjectMethodsWhenMissingMockCall() {
+        when("".equals(null)).thenReturn(false);
+    }
+
+    @Test
+    public void shouldMentionFinalAndObjectMethodsWhenVerifying() {
+        verify(mock).equals(null);
+        verify(mock).simpleMethod();
+    }
+
+    @Test
+    public void shouldMentionFinalAndObjectMethodsWhenMisplacedArgumentMatcher() {
+        when(mock.equals(anyObject())).thenReturn(false);
+    }
+
+    @Test
+    public void shouldShowExampleOfCorrectArgumentCapturing() {
+        ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
+        argument.capture();
+        argument.getValue();
+    }
+
+    @Test
+    public void shouldScreamWhenNullPassedInsteadOfAnInterface() {
+        mock(IMethods.class, withSettings().extraInterfaces(List.class, null));
+    }
+
+    @Test
+    public void shouldScreamWhenNonInterfacePassed() {
+        mock(IMethods.class, withSettings().extraInterfaces(LinkedList.class));
+    }
+
+    @Test
+    public void shouldScreamWhenExtraIsTheSame() {
+        mock(IMethods.class, withSettings().extraInterfaces(IMethods.class));
+    }
+
+    @Test
+    public void shouldScreamWhenExtraInterfacesEmpty() {
+        mock(IMethods.class, withSettings().extraInterfaces());
+    }
+
+    @Test
+    public void shouldScreamWhenExtraInterfacesIsANullArray() {
+        mock(IMethods.class, withSettings().extraInterfaces((Class<?>[]) null));
+    }
+
+    @Test
+    public void shouldMentionSpiesWhenVoidMethodIsToldToReturnValue() {
+        List list = mock(List.class);
+        doReturn("foo").when(list).clear();
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationChunkInOrderTest.java b/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationChunkInOrderTest.java
new file mode 100644
index 0000000..40795e4
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationChunkInOrderTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class PointingStackTraceToActualInvocationChunkInOrderTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private IMethods mockTwo;
+    private InOrder inOrder;
+
+    @Before
+    public void setup() {
+        inOrder = inOrder(mock, mockTwo);
+
+        firstChunk();
+        secondChunk();
+        thirdChunk();
+        fourthChunk();
+    }
+
+    private void firstChunk() {
+        mock.simpleMethod(1);
+        mock.simpleMethod(1);
+    }
+    private void secondChunk() {
+        mockTwo.simpleMethod(2);
+        mockTwo.simpleMethod(2);
+    }
+    private void thirdChunk() {
+        mock.simpleMethod(3);
+        mock.simpleMethod(3);
+    }
+    private void fourthChunk() {
+        mockTwo.simpleMethod(4);
+        mockTwo.simpleMethod(4);
+    }
+
+    @Test
+    public void shouldPointStackTraceToPreviousInvocation() {
+        inOrder.verify(mock, times(2)).simpleMethod(anyInt());
+        inOrder.verify(mockTwo, times(2)).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mock).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("secondChunk(");
+        }
+    }
+
+    @Test
+    public void shouldPointToThirdInteractionBecauseAtLeastOnceUsed() {
+        inOrder.verify(mock, atLeastOnce()).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("thirdChunk(");
+        }
+    }
+
+    @Test
+    public void shouldPointToThirdChunkWhenTooLittleActualInvocations() {
+        inOrder.verify(mock, times(2)).simpleMethod(anyInt());
+        inOrder.verify(mockTwo, times(2)).simpleMethod(anyInt());
+        inOrder.verify(mock, atLeastOnce()).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo, times(3)).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("thirdChunk(");
+        }
+    }
+
+    @Test
+    public void shouldPointToFourthChunkBecauseTooManyActualInvocations() {
+        inOrder.verify(mock, atLeastOnce()).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo, times(0)).simpleMethod(anyInt());
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("fourthChunk(");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationInOrderTest.java b/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationInOrderTest.java
new file mode 100644
index 0000000..4919c44
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationInOrderTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+//This is required to make sure stack trace is well filtered when runner is ON
+@RunWith(MockitoJUnitRunner.class)
+public class PointingStackTraceToActualInvocationInOrderTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private IMethods mockTwo;
+    private InOrder inOrder;
+
+    @Before
+    public void setup() {
+        inOrder = inOrder(mock, mockTwo);
+
+        first();
+        second();
+        third();
+        fourth();
+    }
+
+    private void first() {
+        mock.simpleMethod(1);
+    }
+    private void second() {
+        mockTwo.simpleMethod(2);
+    }
+    private void third() {
+        mock.simpleMethod(3);
+    }
+    private void fourth() {
+        mockTwo.simpleMethod(4);
+    }
+
+    @Test
+    public void shouldPointStackTraceToPreviousVerified() {
+        inOrder.verify(mock, atLeastOnce()).simpleMethod(anyInt());
+        inOrder.verify(mockTwo).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mock).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("fourth(");
+        }
+    }
+
+    @Test
+    public void shouldPointToThirdMethod() {
+        inOrder.verify(mock, atLeastOnce()).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("third(");
+        }
+    }
+
+    @Test
+    public void shouldPointToSecondMethod() {
+        inOrder.verify(mock).simpleMethod(anyInt());
+        inOrder.verify(mockTwo).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo, times(3)).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("second(");
+        }
+    }
+
+    @Test
+    public void shouldPointToFirstMethodBecauseOfTooManyActualInvocations() {
+        try {
+            inOrder.verify(mock, times(0)).simpleMethod(anyInt());
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("first(");
+        }
+    }
+
+    @Test
+    public void shouldPointToSecondMethodBecauseOfTooManyActualInvocations() {
+        inOrder.verify(mock).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo, times(0)).simpleMethod(anyInt());
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("second(");
+        }
+    }
+
+    @Test
+    public void shouldPointToFourthMethodBecauseOfTooLittleActualInvocations() {
+        inOrder.verify(mock).simpleMethod(anyInt());
+        inOrder.verify(mockTwo).simpleMethod(anyInt());
+        inOrder.verify(mock).simpleMethod(anyInt());
+
+        try {
+            inOrder.verify(mockTwo, times(3)).simpleMethod(anyInt());
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("fourth(");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationTest.java b/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationTest.java
new file mode 100644
index 0000000..cdc16ef
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/PointingStackTraceToActualInvocationTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.NeverWantedButInvoked;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+//This is required to make sure stack trace is well filtered when runner is ON
+@RunWith(MockitoJUnitRunner.class)
+public class PointingStackTraceToActualInvocationTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private IMethods mockTwo;
+
+    @Before
+    public void setup() {
+        first();
+        second();
+        third();
+        fourth();
+    }
+
+    private void first() {
+        mock.simpleMethod(1);
+    }
+    private void second() {
+        mockTwo.simpleMethod(2);
+    }
+    private void third() {
+        mock.simpleMethod(3);
+    }
+    private void fourth() {
+        mockTwo.simpleMethod(4);
+    }
+
+    @Test
+    public void shouldPointToTooManyInvocationsChunkOnError() {
+        try {
+            verify(mock, times(0)).simpleMethod(1);
+            fail();
+        } catch (NeverWantedButInvoked e) {
+            assertThat(e).hasMessageContaining("first(");
+        }
+    }
+
+    @Test
+    public void shouldNotPointStackTracesToRunnersCode() {
+        try {
+            verify(mock, times(0)).simpleMethod(1);
+            fail();
+        } catch (NeverWantedButInvoked e) {
+            assertThat(e.getMessage()).doesNotContain(".runners.");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stacktrace/StackTraceFilteringTest.java b/src/test/java/org/mockitousage/stacktrace/StackTraceFilteringTest.java
new file mode 100644
index 0000000..8ad5ae0
--- /dev/null
+++ b/src/test/java/org/mockitousage/stacktrace/StackTraceFilteringTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stacktrace;
+
+import org.assertj.core.api.Assertions;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockitoutil.Conditions.firstMethodInStackTrace;
+
+public class StackTraceFilteringTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @After
+    public void resetState() {
+        super.resetState();
+    }
+
+    @Before
+    public void setup() {
+        makeStackTracesClean();
+    }
+
+    @Test
+    public void shouldFilterStackTraceOnVerify() {
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            Assertions.assertThat(e).has(firstMethodInStackTrace("shouldFilterStackTraceOnVerify"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStackTraceOnVerifyNoMoreInteractions() {
+        mock.oneArg(true);
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+            Assertions.assertThat(e).has(firstMethodInStackTrace("shouldFilterStackTraceOnVerifyNoMoreInteractions"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStackTraceOnVerifyZeroInteractions() {
+        mock.oneArg(true);
+        try {
+            verifyZeroInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+            Assertions.assertThat(e).has(firstMethodInStackTrace("shouldFilterStackTraceOnVerifyZeroInteractions"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStacktraceOnMockitoException() {
+        verify(mock);
+        try {
+            verify(mock).oneArg(true);
+            fail();
+        } catch (MockitoException expected) {
+            Assertions.assertThat(expected).has(firstMethodInStackTrace("shouldFilterStacktraceOnMockitoException"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStacktraceWhenVerifyingInOrder() {
+        InOrder inOrder = inOrder(mock);
+        mock.oneArg(true);
+        mock.oneArg(false);
+
+        inOrder.verify(mock).oneArg(false);
+        try {
+            inOrder.verify(mock).oneArg(true);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            Assertions.assertThat(e).has(firstMethodInStackTrace("shouldFilterStacktraceWhenVerifyingInOrder"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStacktraceWhenInOrderThrowsMockitoException() {
+        try {
+            inOrder();
+            fail();
+        } catch (MockitoException expected) {
+            Assertions.assertThat(expected).has(firstMethodInStackTrace("shouldFilterStacktraceWhenInOrderThrowsMockitoException"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStacktraceWhenInOrderVerifies() {
+        try {
+            InOrder inOrder = inOrder(mock);
+            inOrder.verify(null);
+            fail();
+        } catch (MockitoException expected) {
+            Assertions.assertThat(expected).has(firstMethodInStackTrace("shouldFilterStacktraceWhenInOrderVerifies"));
+        }
+    }
+
+    @Test
+    public void shouldFilterStackTraceWhenThrowingExceptionFromMockHandler() {
+        try {
+            when(mock.oneArg(true)).thenThrow(new Exception());
+            fail();
+        } catch (MockitoException expected) {
+            Assertions.assertThat(expected).has(firstMethodInStackTrace("shouldFilterStackTraceWhenThrowingExceptionFromMockHandler"));
+        }
+    }
+
+    @Test
+    public void shouldShowProperExceptionStackTrace() throws Exception {
+        when(mock.simpleMethod()).thenThrow(new RuntimeException());
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (RuntimeException e) {
+            Assertions.assertThat(e).has(firstMethodInStackTrace("shouldShowProperExceptionStackTrace"));
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/BasicStubbingTest.java b/src/test/java/org/mockitousage/stubbing/BasicStubbingTest.java
new file mode 100644
index 0000000..faf250d
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/BasicStubbingTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.CannotVerifyStubOnlyMock;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class BasicStubbingTest extends TestBase {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = mock(IMethods.class);
+    }
+
+    @Test
+    public void should_evaluate_latest_stubbing_first() throws Exception {
+        when(mock.objectReturningMethod(isA(Integer.class))).thenReturn(100);
+        when(mock.objectReturningMethod(200)).thenReturn(200);
+
+        assertEquals(200, mock.objectReturningMethod(200));
+        assertEquals(100, mock.objectReturningMethod(666));
+        assertEquals("default behavior should return null", null, mock.objectReturningMethod("blah"));
+    }
+
+    @Test
+    public void should_stubbing_be_treated_as_interaction() throws Exception {
+        when(mock.booleanReturningMethod()).thenReturn(true);
+
+        mock.booleanReturningMethod();
+
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void should_allow_stubbing_to_string() throws Exception {
+        IMethods mockTwo = mock(IMethods.class);
+        when(mockTwo.toString()).thenReturn("test");
+
+        assertThat(mock.toString()).contains("Mock for IMethods");
+        assertThat(mockTwo.toString()).isEqualTo("test");
+    }
+
+    @Test
+    public void should_stubbing_not_be_treated_as_interaction() {
+        when(mock.simpleMethod("one")).thenThrow(new RuntimeException());
+        doThrow(new RuntimeException()).when(mock).simpleMethod("two");
+
+        verifyZeroInteractions(mock);
+    }
+
+    @Test
+    public void unfinished_stubbing_cleans_up_the_state() {
+        reset(mock);
+        try {
+            when("").thenReturn("");
+            fail();
+        } catch (MissingMethodInvocationException e) {}
+
+        //anything that can cause state validation
+        verifyZeroInteractions(mock);
+    }
+
+    @Test
+    public void should_to_string_mock_name() {
+        IMethods mock = mock(IMethods.class, "mockie");
+        IMethods mockTwo = mock(IMethods.class);
+
+        assertThat(mockTwo.toString()).contains("Mock for IMethods");
+        assertEquals("mockie", "" + mock);
+    }
+
+    class Foo {
+        public final String toString() {
+            return "foo";
+        }
+    }
+
+    @Test
+    public void should_allow_mocking_when_to_string_is_final() throws Exception {
+        mock(Foo.class);
+    }
+
+    @Test
+    public void test_stub_only_not_verifiable() throws Exception {
+        IMethods localMock = mock(IMethods.class, withSettings().stubOnly());
+
+        when(localMock.objectReturningMethod(isA(Integer.class))).thenReturn(100);
+        when(localMock.objectReturningMethod(200)).thenReturn(200);
+
+        assertEquals(200, localMock.objectReturningMethod(200));
+        assertEquals(100, localMock.objectReturningMethod(666));
+        assertEquals("default behavior should return null", null, localMock.objectReturningMethod("blah"));
+
+        try {
+            verify(localMock, atLeastOnce()).objectReturningMethod(eq(200));
+            fail();
+        } catch (CannotVerifyStubOnlyMock e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/CallingRealMethodTest.java b/src/test/java/org/mockitousage/stubbing/CallingRealMethodTest.java
new file mode 100644
index 0000000..84f8f71
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/CallingRealMethodTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.stubbing;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.*;
+
+public class CallingRealMethodTest extends TestBase {
+
+    @Mock
+    TestedObject mock;
+
+    static class TestedObject {
+
+        String value;
+
+        void setValue(String value) {
+            this.value = value;
+        }
+
+        String getValue() {
+            return "HARD_CODED_RETURN_VALUE";
+        }
+
+        String callInternalMethod() {
+            return getValue();
+        }
+    }
+
+    @Test
+    public void shouldAllowCallingInternalMethod() {
+        when(mock.getValue()).thenReturn("foo");
+        when(mock.callInternalMethod()).thenCallRealMethod();
+
+        assertEquals("foo", mock.callInternalMethod());
+    }
+
+    @Test
+    public void shouldReturnRealValue() {
+        when(mock.getValue()).thenCallRealMethod();
+
+        Assert.assertEquals("HARD_CODED_RETURN_VALUE", mock.getValue());
+    }
+
+    @Test
+    public void shouldExecuteRealMethod() {
+        doCallRealMethod().when(mock).setValue(anyString());
+
+        mock.setValue("REAL_VALUE");
+
+        Assert.assertEquals("REAL_VALUE", mock.value);
+    }
+
+    @Test
+    public void shouldCallRealMethodByDefault() {
+        TestedObject mock = mock(TestedObject.class, CALLS_REAL_METHODS);
+
+        Assert.assertEquals("HARD_CODED_RETURN_VALUE", mock.getValue());
+    }
+
+    @Test
+    public void shouldNotCallRealMethodWhenStubbedLater() {
+        TestedObject mock = mock(TestedObject.class);
+
+        when(mock.getValue()).thenCallRealMethod();
+        when(mock.getValue()).thenReturn("FAKE_VALUE");
+
+        Assert.assertEquals("FAKE_VALUE", mock.getValue());
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/CloningParameterTest.java b/src/test/java/org/mockitousage/stubbing/CloningParameterTest.java
new file mode 100644
index 0000000..a31f264
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/CloningParameterTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.internal.stubbing.answers.ClonesArguments;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertNotNull;
+import static org.mockito.Mockito.*;
+
+public class CloningParameterTest extends TestBase {
+
+    @Test
+    public void shouldVerifyEvenIfArgumentsWereMutated() throws Exception {
+
+        // given
+        EmailSender emailSender = mock(EmailSender.class, new ClonesArguments());
+
+        // when
+        businessLogic(emailSender);
+
+        // then
+        verify(emailSender).sendEmail(1, new Person("Wes"));
+    }
+
+    private void businessLogic(EmailSender emailSender) {
+        Person person = new Person("Wes");
+        emailSender.sendEmail(1, person);
+        person.emailSent();
+    }
+
+    @Test
+    public void shouldReturnDefaultValueWithCloningAnswer() throws Exception {
+
+        // given
+        EmailSender emailSender = mock(EmailSender.class, new ClonesArguments());
+        when(emailSender.getAllEmails(new Person("Wes"))).thenAnswer(new ClonesArguments());
+
+        // when
+        List<?> emails = emailSender.getAllEmails(new Person("Wes"));
+
+        // then
+        assertNotNull(emails);
+    }
+
+    public class Person {
+
+        private final String name;
+        private boolean emailSent;
+
+        public Person(String name) {
+            this.name = name;
+        }
+
+        public void emailSent() {
+            emailSent = true;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + getOuterType().hashCode();
+            result = prime * result + (emailSent ? 1231 : 1237);
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            Person other = (Person) obj;
+            if (!getOuterType().equals(other.getOuterType()))
+                return false;
+            if (emailSent != other.emailSent)
+                return false;
+            if (name == null) {
+                if (other.name != null)
+                    return false;
+            } else if (!name.equals(other.name))
+                return false;
+            return true;
+        }
+
+        private CloningParameterTest getOuterType() {
+            return CloningParameterTest.this;
+        }
+
+    }
+
+    public interface EmailSender {
+
+        void sendEmail(int i, Person person);
+
+        List<?> getAllEmails(Person person);
+
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java b/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java
new file mode 100644
index 0000000..cf714e7
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.stubbing;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.verification.TooManyActualInvocations;
+import org.mockitoutil.TestBase;
+
+import javax.net.SocketFactory;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.List;
+import java.util.Locale;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.*;
+
+
+public class DeepStubbingTest extends TestBase {
+
+    static class Person {
+        Address address;
+
+        public Address getAddress() {
+            return address;
+        }
+
+        public Address getAddress(String addressName) {
+            return address;
+        }
+
+        public FinalClass getFinalClass() {
+            return null;
+        }
+    }
+
+    static class Address {
+        Street street;
+
+        public Street getStreet() {
+            return street;
+        }
+
+        public Street getStreet(Locale locale) {
+            return street;
+        }
+    }
+
+    static class Street {
+        String name;
+
+        public String getName() {
+            return name;
+        }
+
+        public String getLongName() {
+            return name;
+        }
+    }
+
+    static final class FinalClass {}
+
+    interface First {
+        Second getSecond();
+
+        String getString();
+    }
+
+    interface Second extends List<String> {}
+
+    @Test
+    public void myTest() throws Exception {
+        SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf.createSocket(anyString(), eq(80))).thenReturn(null);
+        sf.createSocket("what", 80);
+    }
+
+    @Test
+    public void simpleCase() throws Exception {
+        OutputStream out = new ByteArrayOutputStream();
+        Socket socket = mock(Socket.class);
+        when(socket.getOutputStream()).thenReturn(out);
+
+        assertSame(out, socket.getOutputStream());
+    }
+
+    /**
+     * Test that deep stubbing works for one intermediate level
+     */
+    @Test
+    public void oneLevelDeep() throws Exception {
+        OutputStream out = new ByteArrayOutputStream();
+
+        SocketFactory socketFactory = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(socketFactory.createSocket().getOutputStream()).thenReturn(out);
+
+        assertSame(out, socketFactory.createSocket().getOutputStream());
+    }
+
+    /**
+     * Test that stubbing of two mocks stubs don't interfere
+     */
+    @Test
+    public void interactions() throws Exception {
+        OutputStream out1 = new ByteArrayOutputStream();
+        OutputStream out2 = new ByteArrayOutputStream();
+
+        SocketFactory sf1 = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf1.createSocket().getOutputStream()).thenReturn(out1);
+
+        SocketFactory sf2 = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf2.createSocket().getOutputStream()).thenReturn(out2);
+
+        assertSame(out1, sf1.createSocket().getOutputStream());
+        assertSame(out2, sf2.createSocket().getOutputStream());
+    }
+
+    /**
+     * Test that stubbing of methods of different arguments don't interfere
+     */
+    @Test
+    public void withArguments() throws Exception {
+        OutputStream out1 = new ByteArrayOutputStream();
+        OutputStream out2 = new ByteArrayOutputStream();
+        OutputStream out3 = new ByteArrayOutputStream();
+
+        SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf.createSocket().getOutputStream()).thenReturn(out1);
+        when(sf.createSocket("google.com", 80).getOutputStream()).thenReturn(out2);
+        when(sf.createSocket("stackoverflow.com", 80).getOutputStream()).thenReturn(out3);
+
+        assertSame(out1, sf.createSocket().getOutputStream());
+        assertSame(out2, sf.createSocket("google.com", 80).getOutputStream());
+        assertSame(out3, sf.createSocket("stackoverflow.com", 80).getOutputStream());
+    }
+
+    /**
+     * Test that deep stubbing work with argument patterns
+     */
+    @Test
+    public void withAnyPatternArguments() throws Exception {
+        OutputStream out = new ByteArrayOutputStream();
+
+        //TODO: should not use javax in case it changes
+        SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf.createSocket(anyString(), anyInt()).getOutputStream()).thenReturn(out);
+
+        assertSame(out, sf.createSocket("google.com", 80).getOutputStream());
+        assertSame(out, sf.createSocket("stackoverflow.com", 8080).getOutputStream());
+    }
+
+    /**
+     * Test that deep stubbing work with argument patterns
+     */
+    @Test
+    public void withComplexPatternArguments() throws Exception {
+        OutputStream out1 = new ByteArrayOutputStream();
+        OutputStream out2 = new ByteArrayOutputStream();
+
+        SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf.createSocket(anyString(), eq(80)).getOutputStream()).thenReturn(out1);
+        when(sf.createSocket(anyString(), eq(8080)).getOutputStream()).thenReturn(out2);
+
+        assertSame(out2, sf.createSocket("stackoverflow.com", 8080).getOutputStream());
+        assertSame(out1, sf.createSocket("google.com", 80).getOutputStream());
+        assertSame(out2, sf.createSocket("google.com", 8080).getOutputStream());
+        assertSame(out1, sf.createSocket("stackoverflow.com", 80).getOutputStream());
+    }
+
+    /**
+     * Test that deep stubbing work with primitive expected values
+     */
+    @Test
+    public void withSimplePrimitive() throws Exception {
+        int a = 32;
+
+        SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf.createSocket().getPort()).thenReturn(a);
+
+        assertEquals(a, sf.createSocket().getPort());
+    }
+
+    /**
+     * Test that deep stubbing work with primitive expected values with
+     * pattern method arguments
+     */
+    @Test
+    public void withPatternPrimitive() throws Exception {
+        int a = 12, b = 23, c = 34;
+
+        SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
+        when(sf.createSocket(eq("stackoverflow.com"), eq(80)).getPort()).thenReturn(a);
+        when(sf.createSocket(eq("google.com"), anyInt()).getPort()).thenReturn(b);
+        when(sf.createSocket(eq("stackoverflow.com"), eq(8080)).getPort()).thenReturn(c);
+
+        assertEquals(b, sf.createSocket("google.com", 80).getPort());
+        assertEquals(c, sf.createSocket("stackoverflow.com", 8080).getPort());
+        assertEquals(a, sf.createSocket("stackoverflow.com", 80).getPort());
+    }
+
+    Person person = mock(Person.class, RETURNS_DEEP_STUBS);
+
+    @Test
+    public void shouldStubbingBasicallyWorkFine() throws Exception {
+        //given
+        given(person.getAddress().getStreet().getName()).willReturn("Norymberska");
+
+        //when
+        String street = person.getAddress().getStreet().getName();
+
+        //then
+        assertEquals("Norymberska", street);
+    }
+
+    @Test
+    public void shouldVerificationBasicallyWorkFine() throws Exception {
+        //given
+        person.getAddress().getStreet().getName();
+
+        //then
+        verify(person.getAddress().getStreet()).getName();
+    }
+
+    @Test
+    public void verification_work_with_argument_Matchers_in_nested_calls() throws Exception {
+        //given
+        person.getAddress("111 Mock Lane").getStreet();
+        person.getAddress("111 Mock Lane").getStreet(Locale.ITALIAN).getName();
+
+        //then
+        verify(person.getAddress(anyString())).getStreet();
+        verify(person.getAddress(anyString()).getStreet(Locale.CHINESE), never()).getName();
+        verify(person.getAddress(anyString()).getStreet(eq(Locale.ITALIAN))).getName();
+    }
+
+    @Test
+    public void deep_stub_return_same_mock_instance_if_invocation_matchers_matches() throws Exception {
+        when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
+
+        person.getAddress("the docks").getStreet().getName();
+
+        assertSame(person.getAddress("the docks").getStreet(), person.getAddress(anyString()).getStreet());
+        assertSame(person.getAddress(anyString()).getStreet(), person.getAddress(anyString()).getStreet());
+        assertSame(person.getAddress("the docks").getStreet(), person.getAddress("the docks").getStreet());
+        assertSame(person.getAddress(anyString()).getStreet(), person.getAddress("the docks").getStreet());
+        assertSame(person.getAddress("111 Mock Lane").getStreet(), person.getAddress("the docks").getStreet());
+    }
+
+    @Test
+    public void times_never_atLeast_atMost_verificationModes_should_work() throws Exception {
+        when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
+
+        person.getAddress("the docks").getStreet().getName();
+        person.getAddress("the docks").getStreet().getName();
+        person.getAddress("the docks").getStreet().getName();
+        person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
+
+        verify(person.getAddress("the docks").getStreet(), times(3)).getName();
+        verify(person.getAddress("the docks").getStreet(Locale.CHINESE), never()).getName();
+        verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atMost(1)).getName();
+    }
+
+
+    @Test
+    public void inOrder_only_work_on_the_very_last_mock_but_it_works() throws Exception {
+        when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
+        when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep");
+        when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep");
+
+        person.getAddress("the docks").getStreet().getName();
+        person.getAddress("the docks").getStreet().getLongName();
+        person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
+        person.getAddress("the docks").getStreet(Locale.CHINESE).getName();
+
+        InOrder inOrder = inOrder(
+                person.getAddress("the docks").getStreet(),
+                person.getAddress("the docks").getStreet(Locale.CHINESE),
+                person.getAddress("the docks").getStreet(Locale.ITALIAN)
+        );
+        inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();
+        inOrder.verify(person.getAddress("the docks").getStreet()).getLongName();
+        inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1)).getName();
+        inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();
+    }
+
+    @Test
+    public void verificationMode_only_work_on_the_last_returned_mock() throws Exception {
+        // 1st invocation on Address mock (stubbing)
+        when(person.getAddress("the docks").getStreet().getName()).thenReturn("deep");
+
+        // 2nd invocation on Address mock (real)
+        person.getAddress("the docks").getStreet().getName();
+        // 3rd invocation on Address mock (verification)
+        // (Address mock is not in verification mode)
+        verify(person.getAddress("the docks").getStreet()).getName();
+
+        try {
+            verify(person.getAddress("the docks"), times(1)).getStreet();
+            fail();
+        } catch (TooManyActualInvocations e) {
+            Assertions.assertThat(e.getMessage())
+                    .contains("Wanted 1 time")
+                    .contains("But was 3 times");
+        }
+    }
+
+    @Test
+    public void shouldFailGracefullyWhenClassIsFinal() throws Exception {
+        //when
+        FinalClass value = new FinalClass();
+        given(person.getFinalClass()).willReturn(value);
+
+        //then
+        assertEquals(value, person.getFinalClass());
+    }
+
+    @Test
+    public void deep_stub_does_not_try_to_mock_generic_final_classes() {
+        First first = mock(First.class, RETURNS_DEEP_STUBS);
+        assertNull(first.getString());
+        assertNull(first.getSecond().get(0));
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/ReturningDefaultValuesTest.java b/src/test/java/org/mockitousage/stubbing/ReturningDefaultValuesTest.java
new file mode 100644
index 0000000..571292f
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/ReturningDefaultValuesTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+@SuppressWarnings("unchecked")
+public class ReturningDefaultValuesTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Test
+    public void shouldReturnAllKindsOfPrimitives() throws Exception {
+        assertEquals((byte) 0, mock.byteReturningMethod());
+        assertEquals((short) 0, mock.shortReturningMethod());
+        assertEquals(0, mock.intReturningMethod());
+        assertEquals(0L, mock.longReturningMethod());
+        assertEquals(0.0F, mock.floatReturningMethod(), 0.0F);
+        assertEquals(0.0D, mock.doubleReturningMethod(), 0.0D);
+        assertEquals((char) 0, mock.charReturningMethod());
+        assertEquals(false, mock.booleanReturningMethod());
+        assertEquals(null, mock.objectReturningMethod());
+    }
+
+    @Test
+    public void shouldReturnTheSameValuesForWrapperClasses() throws Exception {
+        assertEquals(new Byte((byte) 0), mock.byteObjectReturningMethod());
+        assertEquals(new Short((short) 0), mock.shortObjectReturningMethod());
+        assertEquals(new Integer(0), mock.integerReturningMethod());
+        assertEquals(new Long(0L), mock.longObjectReturningMethod());
+        assertEquals(new Float(0.0F), mock.floatObjectReturningMethod(), 0.0F);
+        assertEquals(new Double(0.0D), mock.doubleObjectReturningMethod(), 0.0D);
+        assertEquals(new Character((char) 0), mock.charObjectReturningMethod());
+        assertEquals(new Boolean(false), mock.booleanObjectReturningMethod());
+    }
+
+    @Test
+    public void shouldReturnEmptyCollections() {
+        CollectionsServer mock = Mockito.mock(CollectionsServer.class);
+
+        assertTrue(mock.list().isEmpty());
+        assertTrue(mock.linkedList().isEmpty());
+        assertTrue(mock.map().isEmpty());
+        assertTrue(mock.hashSet().isEmpty());
+    }
+
+    @Test
+    public void shouldReturnMutableEmptyCollection() {
+        CollectionsServer mock = Mockito.mock(CollectionsServer.class);
+
+        List list = mock.list();
+        list.add("test");
+
+        assertTrue(mock.list().isEmpty());
+    }
+
+    private class CollectionsServer {
+        List<?> list() {
+            return null;
+        }
+
+        LinkedList<?> linkedList() {
+            return null;
+        }
+
+        Map<?, ?> map() {
+            return null;
+        }
+
+        HashSet<?> hashSet() {
+            return null;
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/SmartNullsStubbingTest.java b/src/test/java/org/mockitousage/stubbing/SmartNullsStubbingTest.java
new file mode 100644
index 0000000..7ddf919
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/SmartNullsStubbingTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.SmartNullPointerException;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class SmartNullsStubbingTest extends TestBase {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = mock(IMethods.class, Mockito.RETURNS_SMART_NULLS);
+    }
+
+    public IMethods unstubbedMethodInvokedHere(IMethods mock) {
+        return mock.iMethodsReturningMethod();
+    }
+
+    @Test
+    public void shouldSmartNPEPointToUnstubbedCall() throws Exception {
+        IMethods methods = unstubbedMethodInvokedHere(mock);
+        try {
+            methods.simpleMethod();
+            fail();
+        } catch (SmartNullPointerException e) {
+            assertThat(e).hasMessageContaining("unstubbedMethodInvokedHere(");
+        }
+    }
+
+    interface Bar {
+        void boo();
+    }
+
+    class Foo {
+        Foo getSomeClass() {
+            return null;
+        }
+
+        Bar getSomeInterface() {
+            return null;
+        }
+
+        Bar getBarWithParams(int x, String y) {
+            return null;
+        }
+
+        void boo() {}
+    }
+
+    @Test
+    public void shouldThrowSmartNPEWhenMethodReturnsClass() throws Exception {
+        Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+        Foo foo = mock.getSomeClass();
+        try {
+            foo.boo();
+            fail();
+        } catch (SmartNullPointerException e) {}
+    }
+
+    @Test
+    public void shouldThrowSmartNPEWhenMethodReturnsInterface() throws Exception {
+        Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+        Bar bar = mock.getSomeInterface();
+        try {
+            bar.boo();
+            fail();
+        } catch (SmartNullPointerException e) {}
+    }
+
+
+    @Test
+    public void shouldReturnOrdinaryEmptyValuesForOrdinaryTypes() throws Exception {
+        IMethods mock = mock(IMethods.class, RETURNS_SMART_NULLS);
+
+        assertEquals("", mock.stringReturningMethod());
+        assertEquals(0, mock.intReturningMethod());
+        assertEquals(true, mock.listReturningMethod().isEmpty());
+        assertEquals(0, mock.arrayReturningMethod().length);
+    }
+
+    @Test
+    public void shouldNotThrowSmartNullPointerOnToString() {
+        Object smartNull = mock.objectReturningMethod();
+        try {
+            verify(mock).simpleMethod(smartNull);
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+
+    @Test
+    public void shouldNotThrowSmartNullPointerOnObjectMethods() {
+        Object smartNull = mock.objectReturningMethod();
+        smartNull.toString();
+    }
+
+    @Test
+    public void shouldShowParameters() {
+        Foo foo = mock(Foo.class, RETURNS_SMART_NULLS);
+        Bar smartNull = foo.getBarWithParams(10, "yes sir");
+
+        try {
+            smartNull.boo();
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("yes sir");
+        }
+    }
+
+    @Test
+    public void shouldShowParametersWhenParamsAreHuge() {
+        Foo foo = mock(Foo.class, RETURNS_SMART_NULLS);
+        String longStr = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
+        Bar smartNull = foo.getBarWithParams(10, longStr);
+
+        try {
+            smartNull.boo();
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("Lorem Ipsum");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StrictStubbingEndToEndTest.java b/src/test/java/org/mockitousage/stubbing/StrictStubbingEndToEndTest.java
new file mode 100644
index 0000000..3780fe2
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StrictStubbingEndToEndTest.java
@@ -0,0 +1,157 @@
+package org.mockitousage.stubbing;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.StateMaster;
+import org.mockito.exceptions.misusing.PotentialStubbingProblem;
+import org.mockito.exceptions.misusing.UnfinishedMockingSessionException;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.quality.Strictness;
+import org.mockitousage.IMethods;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.mockito.BDDMockito.given;
+import static org.mockitoutil.ConcurrentTesting.concurrently;
+import static org.mockitoutil.JUnitResultAssert.assertThat;
+
+public class StrictStubbingEndToEndTest {
+
+    JUnitCore junit = new JUnitCore();
+
+    @After public void after() {
+        new StateMaster().clearMockitoListeners();
+    }
+
+    @Test public void finish_mocking_exception_does_not_hide_the_exception_from_test() {
+        Result result = junit.run(UnnecessaryStubbing.class);
+        assertThat(result)
+                //both exceptions are reported to JUnit:
+                .fails("unnecessary_stubbing", IllegalStateException.class)
+                .fails("unnecessary_stubbing", UnnecessaryStubbingException.class);
+    }
+
+    @Test public void does_not_report_unused_stubbing_if_mismatch_reported() {
+        Result result = junit.run(ReportMismatchButNotUnusedStubbing.class);
+        assertThat(result).fails(1, PotentialStubbingProblem.class);
+    }
+
+    @Test public void strict_stubbing_does_not_leak_to_other_tests() {
+        Result result = junit.run(LenientStrictness1.class, StrictStubsPassing.class, LenientStrictness2.class);
+        //all tests pass, lenient test cases contain incorrect stubbing
+        assertThat(result).succeeds(5);
+    }
+
+    @Test public void detects_unfinished_session() {
+        Result result = junit.run(UnfinishedMocking.class);
+        assertThat(result)
+            .fails(UnfinishedMockingSessionException.class, "\n" +
+                "Unfinished mocking session detected.\n" +
+                "Previous MockitoSession was not concluded with 'finishMocking()'.\n" +
+                "For examples of correct usage see javadoc for MockitoSession class.");
+    }
+
+    @Test public void concurrent_sessions_in_different_threads() throws Exception {
+        final Map<Class, Result> results = new ConcurrentHashMap<Class, Result>();
+        concurrently(new Runnable() {
+                         public void run() {
+                             results.put(StrictStubsPassing.class, junit.run(StrictStubsPassing.class));
+                         }
+                     }, new Runnable() {
+                         public void run() {
+                             results.put(ReportMismatchButNotUnusedStubbing.class, junit.run(ReportMismatchButNotUnusedStubbing.class));
+                         }
+                     }
+        );
+
+        assertThat(results.get(StrictStubsPassing.class)).succeeds(1);
+        assertThat(results.get(ReportMismatchButNotUnusedStubbing.class)).fails(1);
+    }
+
+    public static class UnnecessaryStubbing {
+        @Mock IMethods mock;
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void unnecessary_stubbing() {
+            given(mock.simpleMethod("1")).willReturn("one");
+            throw new IllegalStateException();
+        }
+    }
+
+    public static class ReportMismatchButNotUnusedStubbing {
+        @Mock IMethods mock;
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void mismatch() {
+            given(mock.simpleMethod(1)).willReturn("");
+            mock.simpleMethod(2);
+        }
+    }
+
+    public static class StrictStubsPassing {
+        @Mock IMethods mock;
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
+
+        @After public void after() {
+            mockito.finishMocking();
+        }
+
+        @Test public void used() {
+            given(mock.simpleMethod(1)).willReturn("");
+            mock.simpleMethod(1);
+        }
+    }
+
+    public static class LenientStrictness1 {
+        @Mock IMethods mock = Mockito.mock(IMethods.class);
+
+        @Test public void unused() {
+            given(mock.simpleMethod(1)).willReturn("");
+        }
+
+        @Test public void mismatch() {
+            given(mock.simpleMethod(2)).willReturn("");
+            mock.simpleMethod(3);
+        }
+    }
+
+    public static class LenientStrictness2 {
+        @Mock IMethods mock = Mockito.mock(IMethods.class);
+
+        @Test public void unused() {
+            given(mock.simpleMethod(1)).willReturn("");
+        }
+
+        @Test public void mismatch() {
+            given(mock.simpleMethod(2)).willReturn("");
+            mock.simpleMethod(3);
+        }
+    }
+
+    public static class UnfinishedMocking {
+        @Mock IMethods mock;
+        MockitoSession mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
+
+        @Test public void unused() {
+            given(mock.simpleMethod("1")).willReturn("one");
+        }
+
+        @Test public void unused2() {
+            given(mock.simpleMethod("1")).willReturn("one");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StrictStubbingTest.java b/src/test/java/org/mockitousage/stubbing/StrictStubbingTest.java
new file mode 100644
index 0000000..75ff588
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StrictStubbingTest.java
@@ -0,0 +1,97 @@
+package org.mockitousage.stubbing;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.exceptions.misusing.PotentialStubbingProblem;
+import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.quality.Strictness;
+import org.mockitousage.IMethods;
+
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockitoutil.ThrowableAssert.assertThat;
+
+public class StrictStubbingTest {
+
+    @Mock IMethods mock;
+
+    MockitoSession mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
+
+    @After public void after() {
+        //Some tests already invoke below but that's ok
+        mockito.finishMocking();
+    }
+
+    @Test public void no_interactions() throws Throwable {
+        //expect no exception
+        mockito.finishMocking();
+    }
+
+    @Test public void few_interactions() throws Throwable {
+        mock.simpleMethod(100);
+        mock.otherMethod();
+    }
+
+    @Test public void few_verified_interactions() throws Throwable {
+        //when
+        mock.simpleMethod(100);
+        mock.otherMethod();
+
+        //and
+        verify(mock).simpleMethod(100);
+        verify(mock).otherMethod();
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test public void stubbed_method_is_implicitly_verified() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+        mock.simpleMethod(100);
+
+        //no exceptions:
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test public void unused_stubbed_is_not_implicitly_verified() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+        mock.simpleMethod(100); // <- implicitly verified
+        mock.simpleMethod(200); // <- unverified
+
+        //expect
+        assertThat(new Runnable() {
+            public void run() {
+                verifyNoMoreInteractions(mock);
+            }
+        }).throwsException(NoInteractionsWanted.class);
+    }
+
+    @Test public void stubbing_argument_mismatch() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+
+        //stubbing argument mismatch is detected
+        assertThat(new Runnable() {
+            public void run() {
+                mock.simpleMethod(200);
+            }
+        }).throwsException(PotentialStubbingProblem.class);
+    }
+
+    @Test public void unused_stubbing() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+
+        //unused stubbing is reported
+        assertThat(new Runnable() {
+            public void run() {
+                mockito.finishMocking();
+            }
+        }).throwsException(UnnecessaryStubbingException.class);
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java b/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java
new file mode 100644
index 0000000..c411236
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.*;
+
+public class StubbingConsecutiveAnswersTest extends TestBase {
+
+    @Mock
+    private IMethods mock;
+
+    @Test
+    public void should_return_consecutive_values() throws Exception {
+        when(mock.simpleMethod())
+                .thenReturn("one")
+                .thenReturn("two")
+                .thenReturn("three");
+
+        assertEquals("one", mock.simpleMethod());
+        assertEquals("two", mock.simpleMethod());
+        assertEquals("three", mock.simpleMethod());
+        assertEquals("three", mock.simpleMethod());
+        assertEquals("three", mock.simpleMethod());
+    }
+
+    @Test
+    public void should_return_consecutive_values_for_two_nulls() throws Exception {
+        when(mock.simpleMethod()).thenReturn(null, (String[]) null);
+
+        assertNull(mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+    }
+
+    @Test
+    public void should_return_consecutive_values_set_by_shorten_then_return_method() throws Exception {
+        when(mock.simpleMethod()).thenReturn("one", "two", "three");
+
+        assertEquals("one", mock.simpleMethod());
+        assertEquals("two", mock.simpleMethod());
+        assertEquals("three", mock.simpleMethod());
+        assertEquals("three", mock.simpleMethod());
+        assertEquals("three", mock.simpleMethod());
+    }
+
+    @Test
+    public void should_return_consecutive_value_and_throw_exceptions_set_by_shorten_return_methods() {
+        when(mock.simpleMethod()).thenReturn("zero")
+                                 .thenReturn("one", "two")
+                                 .thenThrow(new NullPointerException(), new RuntimeException())
+                                 .thenReturn("three")
+                                 .thenThrow(new IllegalArgumentException());
+
+        assertEquals("zero", mock.simpleMethod());
+        assertEquals("one", mock.simpleMethod());
+        assertEquals("two", mock.simpleMethod());
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (RuntimeException expected) { }
+        assertEquals("three", mock.simpleMethod());
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void should_throw_consecutively() throws Exception {
+        when(mock.simpleMethod()).thenThrow(new RuntimeException())
+                                 .thenThrow(new IllegalArgumentException())
+                                 .thenThrow(new NullPointerException());
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (RuntimeException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+    }
+
+    @Test
+    public void should_throw_consecutively_set_by_shorten_then_throw_method() throws Exception {
+        when(mock.simpleMethod()).thenThrow(new RuntimeException(),
+                                            new IllegalArgumentException(),
+                                            new NullPointerException());
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (RuntimeException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+    }
+
+    @Test
+    public void should_throw_classes() throws Exception {
+        // Unavoidable JDK7+ 'unchecked generic array creation' warning
+        when(mock.simpleMethod()).thenThrow(IllegalArgumentException.class);
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void should_throw_consecutively_classes_set_by_shorten_then_throw_method() throws Exception {
+        // Unavoidable JDK7+ 'unchecked generic array creation' warning
+        when(mock.simpleMethod()).thenThrow(RuntimeException.class,
+                                            IllegalArgumentException.class,
+                                            NullPointerException.class);
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (RuntimeException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+    }
+
+    @Test
+    public void should_mix_consecutive_returns_with_excepions() throws Exception {
+        when(mock.simpleMethod())
+                .thenThrow(new IllegalArgumentException())
+                .thenReturn("one")
+                .thenThrow(new NullPointerException())
+                .thenReturn(null);
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+
+        assertEquals("one", mock.simpleMethod());
+
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+
+        assertEquals(null, mock.simpleMethod());
+        assertEquals(null, mock.simpleMethod());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_validate_consecutive_exception() throws Exception {
+        when(mock.simpleMethod())
+                .thenReturn("one")
+                .thenThrow(new Exception());
+    }
+
+    @Test
+    public void should_stub_void_method_and_continue_throwing() throws Exception {
+        doThrow(new IllegalArgumentException())
+        .doNothing()
+        .doThrow(new NullPointerException())
+        .when(mock).voidMethod();
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (IllegalArgumentException expected) { }
+
+        mock.voidMethod();
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+    }
+
+    @Test
+    public void should_stub_void_method() throws Exception {
+        doNothing()
+        .doThrow(new NullPointerException())
+        .doNothing()
+        .when(mock)
+        .voidMethod();
+
+        mock.voidMethod();
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (NullPointerException expected) { }
+
+        mock.voidMethod();
+        mock.voidMethod();
+    }
+
+    @Test(expected = MockitoException.class)
+    public void should_validate_consecutive_exception_for_void_method() throws Exception {
+        doNothing()
+        .doThrow(new Exception())
+        .when(mock)
+        .voidMethod();
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingReturnsSelfTest.java b/src/test/java/org/mockitousage/stubbing/StubbingReturnsSelfTest.java
new file mode 100644
index 0000000..d6b1f18
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingReturnsSelfTest.java
@@ -0,0 +1,151 @@
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class StubbingReturnsSelfTest {
+
+    @Test
+    public void should_stub_builder_method() {
+        Builder builder = mock(Builder.class, RETURNS_SELF);
+
+        assertThat(builder.returnSelf()).isEqualTo(builder);
+    }
+
+    @Test
+    public void should_return_default_return_when_not_a_builder() {
+        Builder builder = mock(Builder.class, RETURNS_SELF);
+
+        assertThat(builder.returnString()).isEqualTo(null);
+    }
+
+    @Test
+    public void should_return_self_when_call_on_method_in_superclass() {
+        BuilderSubClass builder = mock(BuilderSubClass.class, RETURNS_SELF);
+
+        assertThat(builder.returnSelf()).isEqualTo(builder);
+    }
+
+    @Test
+    public void should_return_self_when_call_on_method_in_subclass() {
+        BuilderSubClass builder = mock(BuilderSubClass.class, RETURNS_SELF);
+
+        assertThat(builder.returnsSubClass()).isEqualTo(builder);
+    }
+
+    @Test
+    public void should_return_self_when_call_on_method_in_subclass_returns_superclass() {
+        BuilderSubClass builder = mock(BuilderSubClass.class, RETURNS_SELF);
+
+        assertThat(builder.returnSuperClass()).isEqualTo(builder);
+    }
+
+    @Test
+    public void should_return_stubbed_answer_when_call_on_method_returns_self() {
+        Builder builder = mock(Builder.class, RETURNS_SELF);
+        Builder anotherBuilder = mock(Builder.class, RETURNS_SELF);
+
+        when(builder.returnSelf()).thenReturn(anotherBuilder);
+
+        assertThat(builder.returnSelf().returnSelf()).isEqualTo(anotherBuilder);
+    }
+
+    @Test
+    public void should_not_fail_when_calling_void_returning_method() {
+        Builder builder = mock(Builder.class, RETURNS_SELF);
+
+        builder.returnNothing();
+    }
+
+    @Test
+    public void should_not_fail_when_calling_primitive_returning_method() {
+        Builder builder = mock(Builder.class, RETURNS_SELF);
+
+        assertThat(builder.returnInt()).isEqualTo(0);
+    }
+
+    @Test
+    public void use_full_builder_with_terminating_method() {
+        HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF);
+        HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder);
+        String response = "StatusCode: 200";
+
+        when(builder.request()).thenReturn(response);
+
+        assertThat(requester.request("URI")).isEqualTo(response);
+    }
+
+    private static class Builder {
+
+        public Builder returnSelf() {
+            return this;
+        }
+
+        public String returnString() {
+            return "Self";
+        }
+
+        public void returnNothing() {}
+
+        public int returnInt() {
+            return 1;
+        }
+    }
+
+    private static class BuilderSubClass extends Builder {
+
+        public BuilderSubClass returnsSubClass() {
+            return this;
+        }
+
+        public Builder returnSuperClass() {
+            return this;
+        }
+    }
+
+    private static class HttpRequesterWithHeaders {
+
+        private HttpBuilder builder;
+
+        public HttpRequesterWithHeaders(HttpBuilder builder) {
+            this.builder = builder;
+        }
+
+        public String request(String uri) {
+            return builder.withUrl(uri)
+                    .withHeader("Content-type: application/json")
+                    .withHeader("Authorization: Bearer")
+                    .request();
+        }
+    }
+
+    private static class HttpBuilder {
+
+        private String uri;
+        private List<String> headers;
+
+        public HttpBuilder() {
+            this.headers = new ArrayList<String>();
+        }
+
+        public HttpBuilder withUrl(String uri) {
+            this.uri = uri;
+            return this;
+        }
+
+        public HttpBuilder withHeader(String header) {
+            this.headers.add(header);
+            return this;
+        }
+
+        public String request() {
+            return uri + headers.toString();
+        }
+
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingUsingDoReturnTest.java b/src/test/java/org/mockitousage/stubbing/StubbingUsingDoReturnTest.java
new file mode 100644
index 0000000..c9bc37d
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingUsingDoReturnTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.assertj.core.api.Assertions;
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitousage.IMethods;
+import org.mockitousage.MethodsImpl;
+import org.mockitoutil.TestBase;
+
+import java.io.IOException;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("serial")
+public class StubbingUsingDoReturnTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @After public void reset_state() {
+        super.resetState();
+    }
+
+    @Test
+    public void should_stub() throws Exception {
+        doReturn("foo").when(mock).simpleMethod();
+        doReturn("bar").when(mock).simpleMethod();
+
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_stub_with_args() throws Exception {
+        doReturn("foo").when(mock).simpleMethod("foo");
+        doReturn("bar").when(mock).simpleMethod(eq("one"), anyInt());
+
+        Assertions.assertThat(mock.simpleMethod("foo")).isEqualTo("foo");
+        Assertions.assertThat(mock.simpleMethod("one", 234)).isEqualTo("bar");
+        Assertions.assertThat(mock.simpleMethod("xxx", 234)).isEqualTo(null);
+    }
+
+    class FooRuntimeException extends RuntimeException {}
+
+    @Test
+    public void should_stub_with_throwable() throws Exception {
+        doThrow(new FooRuntimeException()).when(mock).voidMethod();
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (FooRuntimeException e) {}
+    }
+
+    @Test
+    public void should_allow_setting_valid_checked_exception() throws Exception {
+        doThrow(new IOException()).when(mock).throwsIOException(0);
+
+        try {
+            mock.throwsIOException(0);
+            fail();
+        } catch (IOException e) {}
+    }
+
+    class FooCheckedException extends Exception {}
+
+    @Test
+    public void should_detect_invalid_checked_exception() throws Exception {
+        try {
+            doThrow(new FooCheckedException()).when(mock).throwsIOException(0);
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("Checked exception is invalid");
+        }
+    }
+
+    @Test
+    public void should_scream_when_return_set_for_void() throws Exception {
+        try {
+            doReturn("foo").when(mock).voidMethod();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e)
+                .hasMessageContaining("void method")
+                .hasMessageContaining("cannot");
+        }
+    }
+
+    @Test
+    public void should_scream_when_not_a_mock_passed() throws Exception {
+        try {
+            doReturn("foo").when("foo").toString();
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("Argument passed to when() is not a mock");
+        }
+    }
+
+    @Test
+    public void should_scream_when_null_passed() throws Exception {
+        try {
+            doReturn("foo").when((Object) null).toString();
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("Argument passed to when() is null");
+        }
+    }
+
+    @Test
+    public void should_allow_chained_stubbing() {
+        doReturn("foo")
+                .doThrow(new RuntimeException())
+                .doReturn("bar")
+                .when(mock).simpleMethod();
+
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("foo");
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch (RuntimeException expected) { }
+
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("bar");
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("bar");
+    }
+
+    @Test
+    public void should_allow_consecutive_return_values() {
+        doReturn("foo", "bar")
+                .doThrow(new RuntimeException())
+                .doReturn(430L, new byte[0], "qix")
+                .when(mock).objectReturningMethodNoArgs();
+
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo("foo");
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo("bar");
+        try {
+            mock.objectReturningMethodNoArgs();
+            fail("exception not raised");
+        } catch (RuntimeException expected) { }
+
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo(430L);
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo(new byte[0]);
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo("qix");
+        Assertions.assertThat(mock.objectReturningMethodNoArgs()).isEqualTo("qix");
+    }
+
+    @Test
+    public void should_allow_do_call_real_method_in_chained_stubbing() throws Exception {
+        MethodsImpl methods = mock(MethodsImpl.class);
+        doReturn("A").doCallRealMethod()
+                .when(methods).simpleMethod();
+
+        Assertions.assertThat(methods.simpleMethod()).isEqualTo("A");
+        Assertions.assertThat(methods.simpleMethod()).isEqualTo(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void should_allow_chained_stubbing_with_exception_class() throws Exception {
+        doReturn("whatever").doThrow(IllegalArgumentException.class).when(mock).simpleMethod();
+
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("whatever");
+        mock.simpleMethod();
+    }
+
+    @Test
+    public void should_allow_chained_stubbing_on_void_methods() {
+        doNothing()
+                .doNothing()
+                .doThrow(new RuntimeException())
+                .when(mock).voidMethod();
+
+        mock.voidMethod();
+        mock.voidMethod();
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (RuntimeException e) {}
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (RuntimeException e) {}
+    }
+
+    @Test
+    public void should_stub_with_generic_answer() {
+        doAnswer(new Answer<Object>() {
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                return "foo";
+            }
+        })
+        .when(mock).simpleMethod();
+
+        Assertions.assertThat(mock.simpleMethod()).isEqualTo("foo");
+    }
+
+    @Test
+    public void should_not_allow_do_nothing_on_non_voids() {
+        try {
+            doNothing().when(mock).simpleMethod();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e).hasMessageContaining("Only void methods can doNothing()");
+        }
+    }
+
+    @Test
+    public void should_stubbing_be_treated_as_interaction() throws Exception {
+        doReturn("foo").when(mock).simpleMethod();
+        mock.simpleMethod();
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void should_verify_stubbed_call() throws Exception {
+        doReturn("foo").when(mock).simpleMethod();
+        mock.simpleMethod();
+        mock.simpleMethod();
+
+        verify(mock, times(2)).simpleMethod();
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void should_allow_stubbing_to_string() throws Exception {
+        doReturn("test").when(mock).toString();
+        Assertions.assertThat(mock.toString()).isEqualTo("test");
+    }
+
+    @Test
+    public void should_detect_invalid_return_type() throws Exception {
+        try {
+            doReturn("foo").when(mock).booleanObjectReturningMethod();
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("String cannot be returned by booleanObjectReturningMethod()" +
+                    "\n" +
+                    "booleanObjectReturningMethod() should return Boolean");
+        }
+    }
+
+    @Test
+    public void should_detect_when_null_assigned_to_boolean() throws Exception {
+        try {
+            doReturn(null).when(mock).intReturningMethod();
+            fail();
+        } catch (Exception e) {
+            assertThat(e).hasMessageContaining("null cannot be returned by intReturningMethod");
+        }
+    }
+
+    @Test
+    public void should_allow_stubbing_when_types_match_signature() throws Exception {
+        doReturn("foo").when(mock).objectReturningMethodNoArgs();
+        doReturn("foo").when(mock).simpleMethod();
+        doReturn(1).when(mock).intReturningMethod();
+        doReturn(2).when(mock).intReturningMethod();
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWarningsTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWarningsTest.java
new file mode 100644
index 0000000..c5c0ea7
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWarningsTest.java
@@ -0,0 +1,81 @@
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.internal.framework.DefaultMockitoSession;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockito.quality.Strictness;
+import org.mockitousage.IMethods;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.BDDMockito.given;
+import static org.mockitoutil.TestBase.filterLineNo;
+
+public class StubbingWarningsTest {
+
+    @Mock IMethods mock;
+
+    SimpleMockitoLogger logger = new SimpleMockitoLogger();
+    MockitoSession mockito = new DefaultMockitoSession(this, Strictness.WARN, logger);
+
+    @Test public void few_interactions() throws Throwable {
+        //when
+        mock.simpleMethod(100);
+        mock.otherMethod();
+
+        //expect no exception
+        mockito.finishMocking();
+        logger.assertEmpty();
+    }
+
+    @Test public void stubbing_used() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+        mock.simpleMethod(100);
+
+        //then
+        mockito.finishMocking();
+        logger.assertEmpty();
+    }
+
+    @Test public void unused_stubbed_is_not_implicitly_verified() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+        mock.simpleMethod(100); // <- stubbing is used
+        mock.simpleMethod(200); // <- other method should not generate arg mismatch
+
+        //then
+        mockito.finishMocking();
+        logger.assertEmpty();
+    }
+
+    @Test public void stubbing_argument_mismatch() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+        mock.simpleMethod(200);
+
+        mockito.finishMocking();
+
+        //TODO - currently we warn about "Unused" instead of "Arg mismatch" below
+        //because it was simpler to implement. This can be improved given we put priority to improve the warnings.
+        //then
+        assertEquals(filterLineNo(
+            "[MockitoHint] StubbingWarningsTest.null (see javadoc for MockitoHint):\n" +
+            "[MockitoHint] 1. Unused -> at org.mockitousage.stubbing.StubbingWarningsTest.stubbing_argument_mismatch(StubbingWarningsTest.java:0)\n"),
+                filterLineNo(logger.getLoggedInfo()));
+    }
+
+    @Test public void unused_stubbing() throws Throwable {
+        //when
+        given(mock.simpleMethod(100)).willReturn("100");
+
+        mockito.finishMocking();
+
+        //then
+        assertEquals(filterLineNo(
+            "[MockitoHint] StubbingWarningsTest.null (see javadoc for MockitoHint):\n" +
+            "[MockitoHint] 1. Unused -> at org.mockitousage.stubbing.StubbingWarningsTest.unused_stubbing(StubbingWarningsTest.java:0)\n"),
+                filterLineNo(logger.getLoggedInfo()));
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithAdditionalAnswersTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithAdditionalAnswersTest.java
new file mode 100644
index 0000000..e67f711
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithAdditionalAnswersTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.stubbing;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalAnswers.answer;
+import static org.mockito.AdditionalAnswers.answerVoid;
+import static org.mockito.AdditionalAnswers.returnsArgAt;
+import static org.mockito.AdditionalAnswers.returnsFirstArg;
+import static org.mockito.AdditionalAnswers.returnsLastArg;
+import static org.mockito.AdditionalAnswers.returnsSecondArg;
+import static org.mockito.BDDMockito.any;
+import static org.mockito.BDDMockito.anyInt;
+import static org.mockito.BDDMockito.anyObject;
+import static org.mockito.BDDMockito.anyString;
+import static org.mockito.BDDMockito.anyVararg;
+import static org.mockito.BDDMockito.eq;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.mock;
+import static org.mockito.BDDMockito.times;
+import static org.mockito.BDDMockito.verify;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer1;
+import org.mockito.stubbing.Answer2;
+import org.mockito.stubbing.Answer3;
+import org.mockito.stubbing.Answer4;
+import org.mockito.stubbing.Answer5;
+import org.mockito.stubbing.VoidAnswer1;
+import org.mockito.stubbing.VoidAnswer2;
+import org.mockito.stubbing.VoidAnswer3;
+import org.mockito.stubbing.VoidAnswer4;
+import org.mockito.stubbing.VoidAnswer5;
+import org.mockitousage.IMethods;
+
+@RunWith(MockitoJUnitRunner.class)
+public class StubbingWithAdditionalAnswersTest {
+
+    @Mock IMethods iMethods;
+
+    @Test
+    public void can_return_arguments_of_invocation() throws Exception {
+        given(iMethods.objectArgMethod(anyObject())).will(returnsFirstArg());
+        given(iMethods.threeArgumentMethod(eq(0), anyObject(), anyString())).will(returnsSecondArg());
+        given(iMethods.threeArgumentMethod(eq(1), anyObject(), anyString())).will(returnsLastArg());
+
+        assertThat(iMethods.objectArgMethod("first")).isEqualTo("first");
+        assertThat(iMethods.threeArgumentMethod(0, "second", "whatever")).isEqualTo("second");
+        assertThat(iMethods.threeArgumentMethod(1, "whatever", "last")).isEqualTo("last");
+    }
+
+    @Test
+    public void can_return_expanded_arguments_of_invocation() throws Exception {
+        given(iMethods.varargsObject(eq(1), anyVararg())).will(returnsArgAt(3));
+
+        assertThat(iMethods.varargsObject(1, "bob", "alexander", "alice", "carl")).isEqualTo("alice");
+    }
+
+    @Test
+    public void can_return_primitives_or_wrappers() throws Exception {
+        given(iMethods.toIntPrimitive(anyInt())).will(returnsFirstArg());
+        given(iMethods.toIntWrapper(anyInt())).will(returnsFirstArg());
+
+        assertThat(iMethods.toIntPrimitive(1)).isEqualTo(1);
+        assertThat(iMethods.toIntWrapper(1)).isEqualTo(1);
+    }
+
+    @Test
+    public void can_return_based_on_strongly_types_one_parameter_function() throws Exception {
+        given(iMethods.simpleMethod(anyString()))
+                .will(answer(new Answer1<String, String>() {
+                    public String answer(String s) {
+                        return s;
+                    }
+                }));
+
+        assertThat(iMethods.simpleMethod("string")).isEqualTo("string");
+    }
+
+    @Test
+    public void will_execute_a_void_based_on_strongly_typed_one_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+
+        given(iMethods.simpleMethod(anyString()))
+                .will(answerVoid(new VoidAnswer1<String>() {
+                    public void answer(String s) {
+                        target.simpleMethod(s);
+                    }
+                }));
+
+        // invoke on iMethods
+        iMethods.simpleMethod("string");
+
+        // expect the answer to write correctly to "target"
+        verify(target, times(1)).simpleMethod("string");
+    }
+
+    @Test
+    public void can_return_based_on_strongly_typed_two_parameter_function() throws Exception {
+        given(iMethods.simpleMethod(anyString(), anyInt()))
+            .will(answer(new Answer2<String, String, Integer>() {
+                public String answer(String s, Integer i) {
+                    return s + "-" + i;
+                }
+            }));
+
+        assertThat(iMethods.simpleMethod("string",1)).isEqualTo("string-1");
+    }
+
+    @Test
+    public void will_execute_a_void_based_on_strongly_typed_two_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+
+        given(iMethods.simpleMethod(anyString(), anyInt()))
+            .will(answerVoid(new VoidAnswer2<String, Integer>() {
+                public void answer(String s, Integer i) {
+                    target.simpleMethod(s, i);
+                }
+            }));
+
+        // invoke on iMethods
+        iMethods.simpleMethod("string",1);
+
+        // expect the answer to write correctly to "target"
+        verify(target, times(1)).simpleMethod("string", 1);
+    }
+
+    @Test
+    public void can_return_based_on_strongly_typed_three_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+        given(iMethods.threeArgumentMethodWithStrings(anyInt(), anyString(), anyString()))
+                .will(answer(new Answer3<String, Integer, String, String>() {
+                    public String answer(Integer i, String s1, String s2) {
+                        target.threeArgumentMethodWithStrings(i, s1, s2);
+                        return "answered";
+                    }
+                }));
+
+        assertThat(iMethods.threeArgumentMethodWithStrings(1, "string1", "string2")).isEqualTo("answered");
+        verify(target, times(1)).threeArgumentMethodWithStrings(1, "string1", "string2");
+    }
+
+    @Test
+    public void will_execute_a_void_based_on_strongly_typed_three_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+
+        given(iMethods.threeArgumentMethodWithStrings(anyInt(), anyString(), anyString()))
+                .will(answerVoid(new VoidAnswer3<Integer, String, String>() {
+                    public void answer(Integer i, String s1, String s2) {
+                        target.threeArgumentMethodWithStrings(i, s1, s2);
+                    }
+                }));
+
+        // invoke on iMethods
+        iMethods.threeArgumentMethodWithStrings(1, "string1", "string2");
+
+        // expect the answer to write correctly to "target"
+        verify(target, times(1)).threeArgumentMethodWithStrings(1, "string1", "string2");
+    }
+
+    @Test
+        public void can_return_based_on_strongly_typed_four_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+        given(iMethods.fourArgumentMethod(anyInt(), anyString(), anyString(), any(boolean[].class)))
+                .will(answer(new Answer4<String, Integer, String, String, boolean[]>() {
+                    public String answer(Integer i, String s1, String s2, boolean[] a) {
+                        target.fourArgumentMethod(i, s1, s2, a);
+                        return "answered";
+                    }
+                }));
+
+        boolean[] booleanArray = { true, false };
+        assertThat(iMethods.fourArgumentMethod(1, "string1", "string2", booleanArray)).isEqualTo("answered");
+        verify(target, times(1)).fourArgumentMethod(1, "string1", "string2", booleanArray);
+    }
+
+    @Test
+    public void will_execute_a_void_based_on_strongly_typed_four_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+
+        given(iMethods.fourArgumentMethod(anyInt(), anyString(), anyString(), any(boolean[].class)))
+                .will(answerVoid(new VoidAnswer4<Integer, String, String, boolean[]>() {
+                    public void answer(Integer i, String s1, String s2, boolean[] a) {
+                        target.fourArgumentMethod(i, s1, s2, a);
+                    }
+                }));
+
+        // invoke on iMethods
+        boolean[] booleanArray = { true, false };
+        iMethods.fourArgumentMethod(1, "string1", "string2", booleanArray);
+
+        // expect the answer to write correctly to "target"
+        verify(target, times(1)).fourArgumentMethod(1, "string1", "string2", booleanArray);
+    }
+
+    @Test
+    public void can_return_based_on_strongly_typed_five_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+        given(iMethods.simpleMethod(anyString(), anyInt(), anyInt(), anyInt(), anyInt()))
+                .will(answer(new Answer5<String, String, Integer, Integer, Integer, Integer>() {
+                    public String answer(String s1, Integer i1, Integer i2, Integer i3, Integer i4) {
+                        target.simpleMethod(s1, i1, i2, i3, i4);
+                        return "answered";
+                    }
+                }));
+
+        assertThat(iMethods.simpleMethod("hello", 1, 2, 3, 4)).isEqualTo("answered");
+        verify(target, times(1)).simpleMethod("hello", 1, 2, 3, 4);
+    }
+
+    @Test
+    public void will_execute_a_void_based_on_strongly_typed_five_parameter_function() throws Exception {
+        final IMethods target = mock(IMethods.class);
+
+        given(iMethods.simpleMethod(anyString(), anyInt(), anyInt(), anyInt(), anyInt()))
+                .will(answerVoid(new VoidAnswer5<String, Integer, Integer, Integer, Integer>() {
+                    public void  answer(String s1, Integer i1, Integer i2, Integer i3, Integer i4) {
+                        target.simpleMethod(s1, i1, i2, i3, i4);
+                    }
+                }));
+
+        // invoke on iMethods
+        iMethods.simpleMethod("hello", 1, 2, 3, 4);
+
+        // expect the answer to write correctly to "target"
+        verify(target, times(1)).simpleMethod("hello", 1, 2, 3, 4);
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithCustomAnswerTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithCustomAnswerTest.java
new file mode 100644
index 0000000..79c7646
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithCustomAnswerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.*;
+
+public class StubbingWithCustomAnswerTest extends TestBase {
+    @Mock
+    private IMethods mock;
+
+    @Test
+    public void shouldAnswer() throws Exception {
+        when(mock.simpleMethod(anyString())).thenAnswer(new Answer<String>() {
+            public String answer(InvocationOnMock invocation) throws Throwable {
+                String arg =  invocation.getArgument(0);
+
+                return invocation.getMethod().getName() + "-" + arg;
+            }
+        });
+
+        assertEquals("simpleMethod-test", mock.simpleMethod("test"));
+    }
+
+    @Test
+    public void shouldAnswerWithThenAnswerAlias() throws Exception {
+        RecordCall recordCall = new RecordCall();
+        Set<?> mockedSet = (Set<?>) when(mock(Set.class).isEmpty()).then(recordCall).getMock();
+
+        mockedSet.isEmpty();
+
+        assertTrue(recordCall.isCalled());
+    }
+
+    @Test
+    public void shouldAnswerConsecutively() throws Exception {
+        when(mock.simpleMethod())
+                .thenAnswer(new Answer<String>() {
+                    public String answer(InvocationOnMock invocation) throws Throwable {
+                        return invocation.getMethod().getName();
+                    }
+                })
+                .thenReturn("Hello")
+                .thenAnswer(new Answer<String>() {
+                    public String answer(InvocationOnMock invocation) throws Throwable {
+                        return invocation.getMethod().getName() + "-1";
+                    }
+                });
+
+        assertEquals("simpleMethod", mock.simpleMethod());
+        assertEquals("Hello", mock.simpleMethod());
+        assertEquals("simpleMethod-1", mock.simpleMethod());
+        assertEquals("simpleMethod-1", mock.simpleMethod());
+    }
+
+    @Test
+    public void shoudAnswerVoidMethod() throws Exception {
+        RecordCall recordCall = new RecordCall();
+
+        doAnswer(recordCall).when(mock).voidMethod();
+
+        mock.voidMethod();
+        assertTrue(recordCall.isCalled());
+    }
+
+    @Test
+    public void shouldAnswerVoidMethodConsecutively() throws Exception {
+        RecordCall call1 = new RecordCall();
+        RecordCall call2 = new RecordCall();
+
+        doAnswer(call1)
+        .doThrow(new UnsupportedOperationException())
+        .doAnswer(call2)
+        .when(mock).voidMethod();
+
+        mock.voidMethod();
+        assertTrue(call1.isCalled());
+        assertFalse(call2.isCalled());
+
+        try {
+            mock.voidMethod();
+            fail();
+        } catch (UnsupportedOperationException e) {
+        }
+
+        mock.voidMethod();
+        assertTrue(call2.isCalled());
+    }
+
+    @Test
+    public void shouldMakeSureTheInterfaceDoesNotChange() throws Exception {
+        when(mock.simpleMethod(anyString())).thenAnswer(new Answer<String>() {
+            public String answer(InvocationOnMock invocation) throws Throwable {
+                assertTrue(invocation.getArguments().getClass().isArray());
+                assertEquals(Method.class, invocation.getMethod().getClass());
+
+                return "assertions passed";
+            }
+        });
+
+        assertEquals("assertions passed", mock.simpleMethod("test"));
+    }
+
+    private static class RecordCall implements Answer<Object> {
+        private boolean called = false;
+
+        public boolean isCalled() {
+            return called;
+        }
+
+        public Object answer(InvocationOnMock invocation) throws Throwable {
+            called = true;
+            return null;
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateTest.java
new file mode 100644
index 0000000..81b0739
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+import org.mockitousage.MethodsImpl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.AdditionalAnswers.delegatesTo;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+@SuppressWarnings("unchecked")
+public class StubbingWithDelegateTest {
+    public class FakeList<T> {
+        private T value;
+
+        public T get(int i) {
+            return value;
+        }
+
+        public T set(int i, T value) {
+            this.value = value;
+            return value;
+        }
+
+        public int size() {
+            return 10;
+        }
+
+        public ArrayList<T> subList(int fromIndex, int toIndex) {
+            return new ArrayList<T>();
+        }
+    }
+
+    public class FakeListWithWrongMethods<T> {
+        public double size() {
+            return 10;
+        }
+
+        public Collection<T> subList(int fromIndex, int toIndex) {
+            return new ArrayList<T>();
+        }
+    }
+
+    @Test
+    public void when_not_stubbed_delegate_should_be_called() {
+        List<String> delegatedList = new ArrayList<String>();
+        delegatedList.add("un");
+
+        List<String> mock = mock(List.class, delegatesTo(delegatedList));
+
+        mock.add("two");
+
+        assertEquals(2, mock.size());
+    }
+
+    @Test
+    public void when_stubbed_the_delegate_should_not_be_called() {
+        List<String> delegatedList = new ArrayList<String>();
+        delegatedList.add("un");
+        List<String> mock = mock(List.class, delegatesTo(delegatedList));
+
+        doReturn(10).when(mock).size();
+
+        mock.add("two");
+
+        assertEquals(10, mock.size());
+        assertEquals(2, delegatedList.size());
+    }
+
+    @Test
+    public void delegate_should_not_be_called_when_stubbed2() {
+        List<String> delegatedList = new ArrayList<String>();
+        delegatedList.add("un");
+        List<String> mockedList = mock(List.class, delegatesTo(delegatedList));
+
+        doReturn(false).when(mockedList).add(Mockito.anyString());
+
+        mockedList.add("two");
+
+        assertEquals(1, mockedList.size());
+        assertEquals(1, delegatedList.size());
+    }
+
+    @Test
+    public void null_wrapper_dont_throw_exception_from_org_mockito_package() throws Exception {
+        IMethods methods = mock(IMethods.class, delegatesTo(new MethodsImpl()));
+
+        try {
+            byte b = methods.byteObjectReturningMethod(); // real method returns null
+            fail();
+        } catch (Exception e) {
+            assertThat(e.toString()).doesNotContain("org.mockito");
+        }
+    }
+
+    @Test
+    public void instance_of_different_class_can_be_called() {
+        List<String> mock = mock(List.class, delegatesTo(new FakeList<String>()));
+
+        mock.set(1, "1");
+        assertThat(mock.get(1).equals("1"));
+    }
+
+    @Test
+    public void method_with_subtype_return_can_be_called() {
+        List<String> mock = mock(List.class, delegatesTo(new FakeList<String>()));
+
+        List<String> subList = mock.subList(0, 0);
+        assertThat(subList.isEmpty());
+    }
+
+    @Test
+    public void calling_missing_method_should_throw_exception() {
+        List<String> mock = mock(List.class, delegatesTo(new FakeList<String>()));
+
+        try {
+            mock.isEmpty();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.toString()).contains("Methods called on mock must exist");
+        }
+    }
+
+    @Test
+    public void calling_method_with_wrong_primitive_return_should_throw_exception() {
+        List<String> mock = mock(List.class, delegatesTo(new FakeListWithWrongMethods<String>()));
+
+        try {
+            mock.size();
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.toString()).contains("Methods called on delegated instance must have compatible return type");
+        }
+    }
+
+    @Test
+    public void calling_method_with_wrong_reference_return_should_throw_exception() {
+        List<String> mock = mock(List.class, delegatesTo(new FakeListWithWrongMethods<String>()));
+
+        try {
+            mock.subList(0, 0);
+            fail();
+        } catch (MockitoException e) {
+            assertThat(e.toString()).contains("Methods called on delegated instance must have compatible return type");
+        }
+    }
+
+    @Test
+    public void exception_should_be_propagated_from_delegate() throws Exception {
+        final RuntimeException failure = new RuntimeException("angry-method");
+        IMethods methods = mock(IMethods.class, delegatesTo(new MethodsImpl() {
+            @Override
+            public String simpleMethod() {
+                throw failure;
+            }
+        }));
+
+        try {
+            methods.simpleMethod(); // delegate throws an exception
+            fail();
+        } catch (RuntimeException e) {
+            assertThat(e).isEqualTo(failure);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateVarArgsTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateVarArgsTest.java
new file mode 100644
index 0000000..5f41d71
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateVarArgsTest.java
@@ -0,0 +1,46 @@
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalAnswers.delegatesTo;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+public class StubbingWithDelegateVarArgsTest {
+
+    public interface Foo {
+        int bar(String baz, Object... args);
+    }
+
+    private static final class FooImpl implements Foo {
+
+        @Override
+        public int bar(String baz, Object... args) {
+            return args != null ? args.length : -1; // simple return argument count
+        }
+
+    }
+
+    @Test
+    public void should_not_fail_when_calling_varargs_method() {
+        Foo foo = mock(Foo.class, withSettings()
+                .defaultAnswer(delegatesTo(new FooImpl())));
+        assertThat(foo.bar("baz", 12, "45", 67.8)).isEqualTo(3);
+    }
+
+    @Test
+    public void should_not_fail_when_calling_varargs_method_without_arguments() {
+        Foo foo = mock(Foo.class, withSettings()
+                .defaultAnswer(delegatesTo(new FooImpl())));
+        assertThat(foo.bar("baz")).isEqualTo(0);
+        assertThat(foo.bar("baz", new Object[0])).isEqualTo(0);
+    }
+
+    @Test
+    public void should_not_fail_when_calling_varargs_method_with_null_argument() {
+        Foo foo = mock(Foo.class, withSettings()
+                .defaultAnswer(delegatesTo(new FooImpl())));
+        assertThat(foo.bar("baz", (Object[]) null)).isEqualTo(-1);
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithExtraAnswersTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithExtraAnswersTest.java
new file mode 100644
index 0000000..d65875f
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithExtraAnswersTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+import org.mockito.AdditionalAnswers;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.when;
+
+public class StubbingWithExtraAnswersTest extends TestBase {
+
+    @Mock private IMethods mock;
+
+    @Test
+    public void shouldWorkAsStandardMockito() throws Exception {
+        //when
+        List<Integer> list = asList(1, 2, 3);
+        when(mock.objectReturningMethodNoArgs()).thenAnswer(AdditionalAnswers.returnsElementsOf(list));
+
+        //then
+        assertEquals(1, mock.objectReturningMethodNoArgs());
+        assertEquals(2, mock.objectReturningMethodNoArgs());
+        assertEquals(3, mock.objectReturningMethodNoArgs());
+        //last element is returned continuously
+        assertEquals(3, mock.objectReturningMethodNoArgs());
+        assertEquals(3, mock.objectReturningMethodNoArgs());
+    }
+
+    @Test
+    public void shouldReturnNullIfNecessary() throws Exception {
+        //when
+        List<Integer> list = asList(1, null);
+        when(mock.objectReturningMethodNoArgs()).thenAnswer(AdditionalAnswers.returnsElementsOf(list));
+
+        //then
+        assertEquals(1, mock.objectReturningMethodNoArgs());
+        assertEquals(null, mock.objectReturningMethodNoArgs());
+        assertEquals(null, mock.objectReturningMethodNoArgs());
+    }
+
+    @Test
+    public void shouldScreamWhenNullPassed() throws Exception {
+        try {
+            //when
+            AdditionalAnswers.returnsElementsOf(null);
+            //then
+            fail();
+        } catch (MockitoException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java
new file mode 100644
index 0000000..0ccf14f
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.stubbing;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitoutil.TestBase;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings({"serial", "unchecked", "all", "deprecation"})
+public class StubbingWithThrowablesTest extends TestBase {
+
+    private LinkedList mock;
+
+    private Map mockTwo;
+
+    @Before
+    public void setup() {
+        mock = mock(LinkedList.class);
+        mockTwo = mock(HashMap.class);
+    }
+
+    @Test
+    public void shouldStubWithThrowable() throws Exception {
+        IllegalArgumentException expected = new IllegalArgumentException("thrown by mock");
+        when(mock.add("throw")).thenThrow(expected);
+
+        try {
+            mock.add("throw");
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals(expected, e);
+        }
+    }
+
+    @Test
+    public void shouldSetThrowableToVoidMethod() throws Exception {
+        IllegalArgumentException expected = new IllegalArgumentException("thrown by mock");
+
+        doThrow(expected).when(mock).clear();
+        try {
+            mock.clear();
+            fail();
+        } catch (Exception e) {
+            assertEquals(expected, e);
+        }
+    }
+
+    @Test
+    public void shouldLastStubbingVoidBeImportant() throws Exception {
+        doThrow(new ExceptionOne()).when(mock).clear();
+        doThrow(new ExceptionTwo()).when(mock).clear();
+
+        try {
+            mock.clear();
+            fail();
+        } catch (ExceptionTwo e) {
+        }
+    }
+
+    @Test
+    public void shouldFailStubbingThrowableOnTheSameInvocationDueToAcceptableLimitation() throws Exception {
+        when(mock.get(1)).thenThrow(new ExceptionOne());
+
+        try {
+            when(mock.get(1)).thenThrow(new ExceptionTwo());
+            fail();
+        } catch (ExceptionOne e) {
+        }
+    }
+
+    @Test
+    public void shouldAllowSettingCheckedException() throws Exception {
+        Reader reader = mock(Reader.class);
+        IOException ioException = new IOException();
+
+        when(reader.read()).thenThrow(ioException);
+
+        try {
+            reader.read();
+            fail();
+        } catch (Exception e) {
+            assertEquals(ioException, e);
+        }
+    }
+
+    @Test
+    public void shouldAllowSettingError() throws Exception {
+        Error error = new Error();
+
+        when(mock.add("quake")).thenThrow(error);
+
+        try {
+            mock.add("quake");
+            fail();
+        } catch (Error e) {
+            assertEquals(error, e);
+        }
+    }
+
+    @Test(expected = MockitoException.class)
+    public void shouldNotAllowNullExceptionType() {
+        when(mock.add(null)).thenThrow((Exception) null);
+    }
+
+
+    @Test(expected = NaughtyException.class)
+    public void shouldInstantiateExceptionClassOnInteraction() {
+        when(mock.add(null)).thenThrow(NaughtyException.class);
+
+        mock.add(null);
+    }
+
+    @Test(expected = NaughtyException.class)
+    public void shouldInstantiateExceptionClassWithOngoingStubbingOnInteraction() {
+        doThrow(NaughtyException.class).when(mock).add(null);
+
+        mock.add(null);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void shouldNotAllowSettingInvalidCheckedException() throws Exception {
+        when(mock.add("monkey island")).thenThrow(new Exception());
+    }
+
+    @Test(expected = MockitoException.class)
+    public void shouldNotAllowSettingNullThrowable() throws Exception {
+        when(mock.add("monkey island")).thenThrow((Throwable) null);
+    }
+
+    @Test(expected = MockitoException.class)
+    public void shouldNotAllowSettingNullThrowableArray() throws Exception {
+        when(mock.add("monkey island")).thenThrow((Throwable[]) null);
+    }
+
+    @Test
+    public void shouldMixThrowablesAndReturnsOnDifferentMocks() throws Exception {
+        when(mock.add("ExceptionOne")).thenThrow(new ExceptionOne());
+        when(mock.getLast()).thenReturn("last");
+        doThrow(new ExceptionTwo()).when(mock).clear();
+
+        doThrow(new ExceptionThree()).when(mockTwo).clear();
+        when(mockTwo.containsValue("ExceptionFour")).thenThrow(new ExceptionFour());
+        when(mockTwo.get("Are you there?")).thenReturn("Yes!");
+
+        assertNull(mockTwo.get("foo"));
+        assertTrue(mockTwo.keySet().isEmpty());
+        assertEquals("Yes!", mockTwo.get("Are you there?"));
+        try {
+            mockTwo.clear();
+            fail();
+        } catch (ExceptionThree e) {
+        }
+        try {
+            mockTwo.containsValue("ExceptionFour");
+            fail();
+        } catch (ExceptionFour e) {
+        }
+
+        assertNull(mock.getFirst());
+        assertEquals("last", mock.getLast());
+        try {
+            mock.add("ExceptionOne");
+            fail();
+        } catch (ExceptionOne e) {
+        }
+        try {
+            mock.clear();
+            fail();
+        } catch (ExceptionTwo e) {
+        }
+    }
+
+    @Test
+    public void shouldStubbingWithThrowableBeVerifiable() {
+        when(mock.size()).thenThrow(new RuntimeException());
+        doThrow(new RuntimeException()).when(mock).clone();
+
+        try {
+            mock.size();
+            fail();
+        } catch (RuntimeException e) {
+        }
+
+        try {
+            mock.clone();
+            fail();
+        } catch (RuntimeException e) {
+        }
+
+        verify(mock).size();
+        verify(mock).clone();
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldStubbingWithThrowableFailVerification() {
+        when(mock.size()).thenThrow(new RuntimeException());
+        doThrow(new RuntimeException()).when(mock).clone();
+
+        verifyZeroInteractions(mock);
+
+        mock.add("test");
+
+        try {
+            verify(mock).size();
+            fail();
+        } catch (WantedButNotInvoked e) {
+        }
+
+        try {
+            verify(mock).clone();
+            fail();
+        } catch (WantedButNotInvoked e) {
+        }
+
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+        }
+    }
+
+    private class ExceptionOne extends RuntimeException {
+
+    }
+
+    private class ExceptionTwo extends RuntimeException {
+
+    }
+
+    private class ExceptionThree extends RuntimeException {
+
+    }
+
+    private class ExceptionFour extends RuntimeException {
+
+    }
+
+    public class NaughtyException extends RuntimeException {
+
+        public NaughtyException() {
+            throw new RuntimeException("boo!");
+        }
+    }
+
+    @Test(expected = NaughtyException.class)
+    public void shouldShowDecentMessageWhenExcepionIsNaughty() throws Exception {
+        when(mock.add("")).thenThrow(NaughtyException.class);
+        mock.add("");
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/AtLeastXVerificationTest.java b/src/test/java/org/mockitousage/verification/AtLeastXVerificationTest.java
new file mode 100644
index 0000000..384829f
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/AtLeastXVerificationTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class AtLeastXVerificationTest extends TestBase {
+
+    @Mock private List<String> mock;
+
+    @Test
+    public void shouldVerifyAtLeastXTimes() throws Exception {
+        //when
+        mock.clear();
+        mock.clear();
+        mock.clear();
+
+        //then
+        verify(mock, atLeast(2)).clear();
+    }
+
+    @Test
+    public void shouldFailVerifiationAtLeastXTimes() throws Exception {
+        mock.add("one");
+        verify(mock, atLeast(1)).add(anyString());
+
+        try {
+            verify(mock, atLeast(2)).add(anyString());
+            fail();
+        } catch (MockitoAssertionError e) {}
+    }
+
+    @Test
+    public void shouldAllowAtLeastZeroForTheSakeOfVerifyNoMoreInteractionsSometimes() throws Exception {
+        //when
+        mock.add("one");
+        mock.clear();
+
+        //then
+        verify(mock, atLeast(0)).add("one");
+        verify(mock, atLeast(0)).clear();
+
+        verifyNoMoreInteractions(mock);
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java b/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java
new file mode 100644
index 0000000..1b048c5
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class AtMostXVerificationTest extends TestBase {
+
+    @Mock private List<String> mock;
+
+    @Test
+    public void shouldVerifyAtMostXTimes() throws Exception {
+        mock.clear();
+        mock.clear();
+
+        verify(mock, atMost(2)).clear();
+        verify(mock, atMost(3)).clear();
+
+        try {
+            verify(mock, atMost(1)).clear();
+            fail();
+        } catch (MockitoAssertionError e) {}
+    }
+
+    @Test
+    public void shouldWorkWithArgumentMatchers() throws Exception {
+        mock.add("one");
+        verify(mock, atMost(5)).add(anyString());
+
+        try {
+            verify(mock, atMost(0)).add(anyString());
+            fail();
+        } catch (MockitoAssertionError e) {}
+    }
+
+    @Test
+    public void shouldNotAllowNegativeNumber() throws Exception {
+        try {
+            verify(mock, atMost(-1)).clear();
+            fail();
+        } catch (MockitoException e) {
+            assertEquals("Negative value is not allowed here", e.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldPrintDecentMessage() throws Exception {
+        mock.clear();
+        mock.clear();
+
+        try {
+            verify(mock, atMost(1)).clear();
+            fail();
+        } catch (MockitoAssertionError e) {
+            assertEquals("\nWanted at most 1 time but was 2", e.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldNotAllowInOrderMode() throws Exception {
+        mock.clear();
+        InOrder inOrder = inOrder(mock);
+
+        try {
+            inOrder.verify(mock, atMost(1)).clear();
+            fail();
+        } catch (MockitoException e) {
+            assertEquals("AtMost is not implemented to work with InOrder", e.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldMarkInteractionsAsVerified() throws Exception {
+        mock.clear();
+        mock.clear();
+
+        verify(mock, atMost(3)).clear();
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldDetectUnverifiedInMarkInteractionsAsVerified() throws Exception {
+        mock.clear();
+        mock.clear();
+        undesiredInteraction();
+
+        verify(mock, atMost(3)).clear();
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch(NoInteractionsWanted e) {
+            assertThat(e).hasMessageContaining("undesiredInteraction(");
+        }
+    }
+
+    private void undesiredInteraction() {
+        mock.add("");
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/BasicVerificationInOrderTest.java b/src/test/java/org/mockitousage/verification/BasicVerificationInOrderTest.java
new file mode 100644
index 0000000..4268b59
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/BasicVerificationInOrderTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class BasicVerificationInOrderTest extends TestBase {
+
+    private IMethods mockOne;
+    private IMethods mockTwo;
+    private IMethods mockThree;
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() {
+        mockOne = mock(IMethods.class);
+        mockTwo = mock(IMethods.class);
+        mockThree = mock(IMethods.class);
+
+        inOrder = inOrder(mockOne, mockTwo, mockThree);
+
+        mockOne.simpleMethod(1);
+        mockTwo.simpleMethod(2);
+        mockTwo.simpleMethod(2);
+        mockThree.simpleMethod(3);
+        mockTwo.simpleMethod(2);
+        mockOne.simpleMethod(4);
+    }
+
+    @Test
+    public void shouldVerifyInOrder() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderUsingAtLeastOnce() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(4);
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderWhenExpectingSomeInvocationsToBeCalledZeroTimes() {
+        inOrder.verify(mockOne, times(0)).oneArg(false);
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockTwo, times(0)).simpleMethod(22);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+        inOrder.verify(mockThree, times(0)).oneArg(false);
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldFailWhenFirstMockCalledTwice() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailWhenLastMockCalledTwice() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+        try {
+            inOrder.verify(mockOne).simpleMethod(4);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test(expected = VerificationInOrderFailure.class)
+    public void shouldFailOnFirstMethodBecauseOneInvocationWanted() {
+        inOrder.verify(mockOne, times(0)).simpleMethod(1);
+    }
+
+    @Test(expected = VerificationInOrderFailure.class)
+    public void shouldFailOnFirstMethodBecauseOneInvocationWantedAgain() {
+        inOrder.verify(mockOne, times(2)).simpleMethod(1);
+    }
+
+    @Test
+    public void shouldFailOnSecondMethodBecauseFourInvocationsWanted() {
+        inOrder.verify(mockOne, times(1)).simpleMethod(1);
+        try {
+            inOrder.verify(mockTwo, times(4)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnSecondMethodBecauseTwoInvocationsWantedAgain() {
+        inOrder.verify(mockOne, times(1)).simpleMethod(1);
+        try {
+            inOrder.verify(mockTwo, times(0)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnLastMethodBecauseOneInvocationWanted() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree, atLeastOnce()).simpleMethod(3);
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne, times(0)).simpleMethod(4);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnLastMethodBecauseOneInvocationWantedAgain() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree, atLeastOnce()).simpleMethod(3);
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne, times(2)).simpleMethod(4);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    /* ------------- */
+
+    @Test(expected = ArgumentsAreDifferent.class)
+    public void shouldFailOnFirstMethodBecauseDifferentArgsWanted() {
+        inOrder.verify(mockOne).simpleMethod(100);
+    }
+
+    @Test(expected = WantedButNotInvoked.class)
+    public void shouldFailOnFirstMethodBecauseDifferentMethodWanted() {
+        inOrder.verify(mockOne).oneArg(true);
+    }
+
+    @Test
+    public void shouldFailOnSecondMethodBecauseDifferentArgsWanted() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        try {
+            inOrder.verify(mockTwo, times(2)).simpleMethod(-999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnSecondMethodBecauseDifferentMethodWanted() {
+        inOrder.verify(mockOne, times(1)).simpleMethod(1);
+        try {
+            inOrder.verify(mockTwo, times(2)).oneArg(true);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnLastMethodBecauseDifferentArgsWanted() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne).simpleMethod(-666);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnLastMethodBecauseDifferentMethodWanted() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne).oneArg(false);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    /* -------------- */
+
+    @Test
+    public void shouldFailWhenLastMethodVerifiedFirst() {
+        inOrder.verify(mockOne).simpleMethod(4);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailWhenMiddleMethodVerifiedFirst() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailWhenMiddleMethodVerifiedFirstInAtLeastOnceMode() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+        }
+    }
+
+    @Test
+    public void shouldFailOnVerifyNoMoreInteractions() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+
+        try {
+            verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+            fail();
+        } catch (NoInteractionsWanted e) {
+        }
+    }
+
+    @Test(expected = NoInteractionsWanted.class)
+    public void shouldFailOnVerifyZeroInteractions() {
+        verifyZeroInteractions(mockOne);
+    }
+
+    @SuppressWarnings("all")
+    @Test(expected = MockitoException.class)
+    public void shouldScreamWhenNullPassed() {
+        inOrder((Object[])null);
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/BasicVerificationTest.java b/src/test/java/org/mockitousage/verification/BasicVerificationTest.java
new file mode 100644
index 0000000..19b984f
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/BasicVerificationTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.TooManyActualInvocations;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class BasicVerificationTest extends TestBase {
+
+    @Mock private List<String> mock;
+    @Mock private List<String> mockTwo;
+
+    @Test
+    public void shouldVerify() throws Exception {
+        mock.clear();
+        verify(mock).clear();
+
+        mock.add("test");
+        verify(mock).add("test");
+
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test(expected=WantedButNotInvoked.class)
+    public void shouldFailVerification() throws Exception {
+        verify(mock).clear();
+    }
+
+    @Test
+    public void shouldFailVerificationOnMethodArgument() throws Exception {
+        mock.clear();
+        mock.add("foo");
+
+        verify(mock).clear();
+        try {
+            verify(mock).add("bar");
+            fail();
+        } catch (AssertionError expected) {}
+    }
+
+    @Test
+    public void shouldFailOnWrongMethod() throws Exception {
+        mock.clear();
+        mock.clear();
+
+        mockTwo.add("add");
+
+        verify(mock, atLeastOnce()).clear();
+        verify(mockTwo, atLeastOnce()).add("add");
+        try {
+            verify(mockTwo, atLeastOnce()).add("foo");
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+
+    @Test
+    public void shouldDetectRedundantInvocation() throws Exception {
+        mock.clear();
+        mock.add("foo");
+        mock.add("bar");
+
+        verify(mock).clear();
+        verify(mock).add("foo");
+
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldDetectWhenInvokedMoreThanOnce() throws Exception {
+        mock.add("foo");
+        mock.clear();
+        mock.clear();
+
+        verify(mock).add("foo");
+
+        try {
+            verify(mock).clear();
+            fail();
+        } catch (TooManyActualInvocations e) {}
+    }
+
+    @Test
+    public void shouldVerifyStubbedMethods() throws Exception {
+        when(mock.add("test")).thenReturn(Boolean.FALSE);
+
+        mock.add("test");
+
+        verify(mock).add("test");
+    }
+
+
+    @Test
+    public void shouldDetectWhenOverloadedMethodCalled() throws Exception {
+        IMethods mockThree = mock(IMethods.class);
+
+        mockThree.varargs((Object[]) new Object[] {});
+        try {
+            verify(mockThree).varargs((String[]) new String[] {});
+            fail();
+        } catch(WantedButNotInvoked e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/CustomVerificationTest.java b/src/test/java/org/mockitousage/verification/CustomVerificationTest.java
new file mode 100644
index 0000000..f0a7de8
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/CustomVerificationTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.verify;
+
+public class CustomVerificationTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @Test
+    public void custom_verification_with_old_api() {
+        //given:
+        mock.simpleMethod("a", 10);
+
+        //expect:
+        verify(mock, ignoreParametersUsingOldApi()).simpleMethod();
+
+        try {
+            verify(mock, ignoreParametersUsingOldApi()).otherMethod();
+            fail();
+        } catch (MockitoAssertionError e) {}
+    }
+
+    //Old api still supported, see https://github.com/mockito/mockito/issues/730
+    private VerificationMode ignoreParametersUsingOldApi() {
+        return new VerificationMode() {
+            public void verify(VerificationData data) {
+                //use old api
+                InvocationMatcher target = data.getWanted();
+
+                //sanity check the new api
+                if (data.getTarget() != target) {
+                    throw new RuntimeException("Sanity check");
+                }
+
+                //look for the relevant invocation and exit if found
+                for (Invocation invocation : data.getAllInvocations()) {
+                    if (target.getInvocation().getMethod().getName().equals(invocation.getMethod().getName())) {
+                        return;
+                    }
+                }
+
+                //verification failed!
+                throw new MockitoAssertionError("Expected method with name: " + target + " not found in:\n" + data.getAllInvocations());
+            }
+            public VerificationMode description(String description) {
+                return this;
+            }
+        };
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/DelayedExecution.java b/src/test/java/org/mockitousage/verification/DelayedExecution.java
new file mode 100644
index 0000000..a0d3d37
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/DelayedExecution.java
@@ -0,0 +1,78 @@
+package org.mockitousage.verification;
+
+import static java.lang.System.currentTimeMillis;
+import static java.lang.Thread.MAX_PRIORITY;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.locks.LockSupport.parkUntil;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+class DelayedExecution {
+    private static final int CORE_POOL_SIZE = 3;
+    /**
+     * Defines the number of milliseconds we expecting a Thread might need to unpark, we use this to avoid "oversleeping" while awaiting the deadline for
+     */
+    private static final long MAX_EXPECTED_OVERSLEEP_MILLIS = 50;
+
+    private final ScheduledExecutorService executor;
+
+    public DelayedExecution() {
+        this.executor = newScheduledThreadPool(CORE_POOL_SIZE, maxPrioThreadFactory());
+    }
+
+    public void callAsync(long delay, TimeUnit timeUnit, Runnable r) {
+        long deadline = timeUnit.toMillis(delay) + currentTimeMillis();
+
+        executor.submit(delayedExecution(r, deadline));
+    }
+
+    public void close() throws InterruptedException {
+        executor.shutdownNow();
+
+        if (!executor.awaitTermination(5, SECONDS)) {
+            throw new IllegalStateException("This delayed excution did not terminated after 5 seconds");
+        }
+    }
+
+    private static Runnable delayedExecution(final Runnable r, final long deadline) {
+        return new Runnable() {
+            @Override
+            public void run() {
+                //we park the current Thread till 50ms before we want to execute the runnable
+                parkUntil(deadline - MAX_EXPECTED_OVERSLEEP_MILLIS);
+                //now we closing to the deadline by burning CPU-time in a loop
+                burnRemaining(deadline);
+
+                System.out.println("[DelayedExecution] exec delay = "+(currentTimeMillis() - deadline)+"ms");
+
+                r.run();
+            }
+
+            /**
+             * Loop in tight cycles until we reach the dead line. We do this cause sleep or park is very not precise,
+             * this can causes a Thread to under- or oversleep, sometimes by +50ms.
+             */
+            private void burnRemaining(final long deadline) {
+                long remaining;
+                do {
+                    remaining = deadline - currentTimeMillis();
+                } while (remaining > 0);
+            }
+        };
+    }
+
+    private static ThreadFactory maxPrioThreadFactory() {
+        return new ThreadFactory() {
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread t = new Thread(r);
+                t.setDaemon(true);  // allows the JVM to exit when clients forget to call DelayedExecution.close()
+                t.setPriority(MAX_PRIORITY);
+                return t;
+            }
+        };
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/DescriptiveMessagesOnVerificationInOrderErrorsTest.java b/src/test/java/org/mockitousage/verification/DescriptiveMessagesOnVerificationInOrderErrorsTest.java
new file mode 100644
index 0000000..f6fe094
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/DescriptiveMessagesOnVerificationInOrderErrorsTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class DescriptiveMessagesOnVerificationInOrderErrorsTest extends TestBase {
+
+    private IMethods one;
+    private IMethods two;
+    private IMethods three;
+    private InOrder inOrder;
+
+    @Before
+    public void setup() {
+        one = Mockito.mock(IMethods.class);
+        two = Mockito.mock(IMethods.class);
+        three = Mockito.mock(IMethods.class);
+
+        one.simpleMethod(1);
+        one.simpleMethod(11);
+        two.simpleMethod(2);
+        two.simpleMethod(2);
+        three.simpleMethod(3);
+
+        inOrder = inOrder(one, two, three);
+    }
+
+    @Test
+    public void shouldPrintVerificationInOrderErrorAndShowBothWantedAndPrevious() {
+        inOrder.verify(one).simpleMethod(1);
+        inOrder.verify(two, atLeastOnce()).simpleMethod(2);
+
+        try {
+            inOrder.verify(one, atLeastOnce()).simpleMethod(11);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            String expected =
+                    "\n" +
+                    "Verification in order failure" +
+                    "\n" +
+                    "Wanted but not invoked:" +
+                    "\n" +
+                    "iMethods.simpleMethod(11);" +
+                    "\n" +
+                    "-> at ";
+
+            assertThat(e).hasMessageContaining(expected);
+
+            String expectedCause =
+                "\n" +
+                "Wanted anywhere AFTER following interaction:" +
+                "\n" +
+                "iMethods.simpleMethod(2);" +
+                "\n" +
+                "-> at ";
+
+            assertThat(e).hasMessageContaining(expectedCause);
+        }
+    }
+
+    @Test
+    public void shouldPrintVerificationInOrderErrorAndShowWantedOnly() {
+        try {
+            inOrder.verify(one).differentMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            String expected =
+                    "\n" +
+                    "Wanted but not invoked:" +
+                    "\n" +
+                    "iMethods.differentMethod();" +
+                    "\n" +
+                    "-> at";
+
+            assertThat(e).hasMessageContaining(expected);
+        }
+    }
+
+    @Test
+    public void shouldPrintVerificationInOrderErrorAndShowWantedAndActual() {
+        try {
+            inOrder.verify(one).simpleMethod(999);
+            fail();
+        } catch (org.mockito.exceptions.verification.junit.ArgumentsAreDifferent e) {
+            assertThat(e).hasMessageContaining("has different arguments");
+        }
+    }
+
+    @Test
+    public void shouldNotSayArgumentsAreDifferent() {
+        //this is the last invocation so any next verification in order should simply say wanted but not invoked
+        inOrder.verify(three).simpleMethod(3);
+        try {
+            inOrder.verify(one).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("Wanted but not invoked");
+        }
+    }
+
+    @Test
+    public void shouldPrintMethodThatWasNotInvoked() {
+        inOrder.verify(one).simpleMethod(1);
+        inOrder.verify(one).simpleMethod(11);
+        inOrder.verify(two, times(2)).simpleMethod(2);
+        inOrder.verify(three).simpleMethod(3);
+        try {
+            inOrder.verify(three).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            String expectedMessage =
+                    "\n" +
+                    "Verification in order failure" +
+                    "\n" +
+                    "Wanted but not invoked:" +
+                    "\n" +
+                    "iMethods.simpleMethod(999);";
+            assertThat(e).hasMessageContaining(expectedMessage);
+        }
+    }
+
+    @Test
+    public void shouldPrintTooManyInvocations() {
+        inOrder.verify(one).simpleMethod(1);
+        inOrder.verify(one).simpleMethod(11);
+        try {
+            inOrder.verify(two, times(1)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            String expectedMessage =
+                    "\n" +
+                    "Verification in order failure:" +
+                    "\n" +
+                    "iMethods.simpleMethod(2);" +
+                    "\n" +
+                    "Wanted 1 time:" +
+                    "\n" +
+                    "-> at";
+            assertThat(e).hasMessageContaining(expectedMessage);
+
+            String expectedCause =
+                "\n" +
+                "But was 2 times. Undesired invocation:" +
+                "\n" +
+                "-> at";
+            assertThat(e).hasMessageContaining(expectedCause);
+        }
+    }
+
+    @Test
+    public void shouldPrintTooLittleInvocations() {
+        two.simpleMethod(2);
+
+        inOrder.verify(one, atLeastOnce()).simpleMethod(anyInt());
+        inOrder.verify(two, times(2)).simpleMethod(2);
+        inOrder.verify(three, atLeastOnce()).simpleMethod(3);
+
+        try {
+            inOrder.verify(two, times(2)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {
+            String expectedMessage =
+                    "\n" +
+                    "Verification in order failure:" +
+                    "\n" +
+                    "iMethods.simpleMethod(2);" +
+                    "\n" +
+                    "Wanted 2 times:" +
+                    "\n" +
+                    "-> at";
+            assertThat(e).hasMessageContaining(expectedMessage);
+
+            String expectedCause =
+                "\n" +
+                "But was 1 time:" +
+                "\n" +
+                "-> at";
+
+            assertThat(e).hasMessageContaining(expectedCause);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/DescriptiveMessagesWhenTimesXVerificationFailsTest.java b/src/test/java/org/mockitousage/verification/DescriptiveMessagesWhenTimesXVerificationFailsTest.java
new file mode 100644
index 0000000..e83cb9c
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/DescriptiveMessagesWhenTimesXVerificationFailsTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.TooManyActualInvocations;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.times;
+
+@SuppressWarnings("unchecked")
+public class DescriptiveMessagesWhenTimesXVerificationFailsTest extends TestBase {
+
+    @Mock private LinkedList mock;
+
+    @Test
+    public void shouldVerifyActualNumberOfInvocationsSmallerThanWanted() throws Exception {
+        mock.clear();
+        mock.clear();
+        mock.clear();
+
+        Mockito.verify(mock, times(3)).clear();
+        try {
+            Mockito.verify(mock, times(100)).clear();
+            fail();
+        } catch (TooLittleActualInvocations e) {
+            assertThat(e)
+                .hasMessageContaining("mock.clear();")
+                .hasMessageContaining("Wanted 100 times")
+                .hasMessageContaining("was 3");
+        }
+    }
+
+    @Test
+    public void shouldVerifyActualNumberOfInvocationsLargerThanWanted() throws Exception {
+        mock.clear();
+        mock.clear();
+        mock.clear();
+        mock.clear();
+
+        Mockito.verify(mock, times(4)).clear();
+        try {
+            Mockito.verify(mock, times(1)).clear();
+            fail();
+        } catch (TooManyActualInvocations e) {
+            assertThat(e)
+                .hasMessageContaining("mock.clear();")
+                .hasMessageContaining("Wanted 1 time")
+                .hasMessageContaining("was 4");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/DescriptiveMessagesWhenVerificationFailsTest.java b/src/test/java/org/mockitousage/verification/DescriptiveMessagesWhenVerificationFailsTest.java
new file mode 100644
index 0000000..72cd98d
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/DescriptiveMessagesWhenVerificationFailsTest.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.NeverWantedButInvoked;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.Mockito.*;
+
+public class DescriptiveMessagesWhenVerificationFailsTest extends TestBase {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = Mockito.mock(IMethods.class, "iMethods");
+    }
+
+    @Test
+    public void should_print_method_name() {
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            String expectedMessage =
+                    "\n" +
+                    "Wanted but not invoked:" +
+                    "\n" +
+                    "iMethods.simpleMethod();" +
+                    "\n" +
+                    "-> at";
+            assertThat(e).hasMessageContaining(expectedMessage);
+        }
+    }
+
+    private class Foo {
+        public String toString() {
+            return "foo";
+        }
+    }
+
+    @Test
+    public void should_print_method_name_and_arguments() {
+        try {
+            verify(mock).threeArgumentMethod(12, new Foo(), "xx");
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("iMethods.threeArgumentMethod(12, foo, \"xx\")");
+        }
+    }
+
+    @Test
+    public void should_print_actual_and_wanted_in_line() {
+        mock.varargs(1, 2);
+
+        try {
+            verify(mock).varargs(1, 1000);
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            String wanted =
+                    "\n" +
+                    "Argument(s) are different! Wanted:" +
+                    "\n" +
+                    "iMethods.varargs(1, 1000);";
+
+            assertThat(e).hasMessageContaining(wanted);
+
+            String actual =
+                    "\n" +
+                    "Actual invocation has different arguments:" +
+                    "\n" +
+                    "iMethods.varargs(1, 2);";
+
+            assertThat(e).hasMessageContaining(actual);
+        }
+    }
+
+    @Test
+    public void should_print_actual_and_wanted_in_multiple_lines() {
+        mock.varargs("this is very long string", "this is another very long string");
+
+        try {
+            verify(mock).varargs("x", "y", "z");
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            String wanted =
+                    "\n" +
+                    "Argument(s) are different! Wanted:" +
+                    "\n" +
+                    "iMethods.varargs(" +
+                    "\n" +
+                    "    \"x\"," +
+                    "\n" +
+                    "    \"y\"," +
+                    "\n" +
+                    "    \"z\"" +
+                    "\n" +
+                    ");";
+
+            assertThat(e).hasMessageContaining(wanted);
+
+            String actual =
+                    "\n" +
+                    "Actual invocation has different arguments:" +
+                    "\n" +
+                    "iMethods.varargs(" +
+                    "\n" +
+                    "    \"this is very long string\"," +
+                    "\n" +
+                    "    \"this is another very long string\"" +
+                    "\n" +
+                    ");";
+
+            assertThat(e).hasMessageContaining(actual);
+        }
+    }
+
+    @Test
+    public void should_print_actual_and_wanted_when_actual_method_name_and_wanted_method_name_are_the_same() {
+        mock.simpleMethod();
+
+        try {
+            verify(mock).simpleMethod(10);
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e).hasMessageContaining("simpleMethod(10)").hasMessageContaining("simpleMethod()");
+        }
+    }
+
+    @Test
+    public void should_print_actual_and_unverified_wanted_when_the_difference_is_about_arguments() {
+        mock.twoArgumentMethod(1, 1);
+        mock.twoArgumentMethod(2, 2);
+
+        verify(mock).twoArgumentMethod(1, 1);
+        try {
+            verify(mock).twoArgumentMethod(2, 1000);
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e).hasMessageContaining("(2, 1000)").hasMessageContaining("(2, 2)");
+        }
+    }
+
+    @Test
+    public void should_print_first_unexpected_invocation() {
+        mock.oneArg(true);
+        mock.oneArg(false);
+        mock.threeArgumentMethod(1, "2", "3");
+
+        verify(mock).oneArg(true);
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+            String expectedMessage =
+                    "\n" +
+                    "No interactions wanted here:" +
+                    "\n" +
+                    "-> at";
+            assertThat(e).hasMessageContaining(expectedMessage);
+
+            String expectedCause =
+                    "\n" +
+                    "But found this interaction on mock '" + mock + "':" +
+                    "\n" +
+                    "-> at";
+            assertThat(e).hasMessageContaining(expectedCause);
+        }
+    }
+
+    @Test
+    public void should_print_first_unexpected_invocation_when_verifying_zero_interactions() {
+        mock.twoArgumentMethod(1, 2);
+        mock.threeArgumentMethod(1, "2", "3");
+
+        try {
+            verifyZeroInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+            String expected =
+                    "\n" +
+                    "No interactions wanted here:" +
+                    "\n" +
+                    "-> at";
+
+            assertThat(e).hasMessageContaining(expected);
+
+            String expectedCause =
+                "\n" +
+                "But found this interaction on mock '" + mock + "':" +
+                "\n" +
+                "-> at";
+
+            assertThat(e).hasMessageContaining(expectedCause);
+        }
+    }
+
+    @Test
+    public void should_print_method_name_when_verifying_at_least_once() throws Exception {
+        try {
+            verify(mock, atLeastOnce()).twoArgumentMethod(1, 2);
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("twoArgumentMethod(1, 2)");
+        }
+    }
+
+    @Test
+    public void should_print_method_when_matcher_used() throws Exception {
+        try {
+            verify(mock, atLeastOnce()).twoArgumentMethod(anyInt(), eq(100));
+            fail();
+        } catch (WantedButNotInvoked e) {
+            String expectedMessage =
+                "\n" +
+                "Wanted but not invoked:" +
+                "\n" +
+                "iMethods.twoArgumentMethod(\n" +
+                "    <any integer>,\n" +
+                "    100\n" +
+                ");";
+            assertThat(e).hasMessageContaining(expectedMessage);
+        }
+    }
+
+    @Test
+    public void should_print_method_when_missing_invocation_with_array_matcher() {
+        mock.oneArray(new boolean[] { true, false, false });
+
+        try {
+            verify(mock).oneArray(aryEq(new boolean[] { false, false, false }));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e)
+                .hasMessageContaining("[false, false, false]")
+                .hasMessageContaining("[true, false, false]");
+        }
+    }
+
+    @Test
+    public void should_print_method_when_missing_invocation_with_vararg_matcher() {
+        mock.varargsString(10, "xxx", "yyy", "zzz");
+
+        try {
+            verify(mock).varargsString(10, "111", "222", "333");
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e)
+                .hasMessageContaining("111")
+                .hasMessageContaining("\"xxx\"");
+        }
+    }
+
+    @Test
+    public void should_print_method_when_missing_invocation_with_matcher() {
+        mock.simpleMethod("foo");
+
+        try {
+            verify(mock).simpleMethod(matches("burrito from Exmouth"));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e)
+                .hasMessageContaining("matches(\"burrito from Exmouth\")")
+                .hasMessageContaining("\"foo\"");
+        }
+    }
+
+    @Test
+    public void should_print_null_arguments() throws Exception {
+        mock.simpleMethod(null, (Integer) null);
+        try {
+            verify(mock).simpleMethod("test");
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e).hasMessageContaining("simpleMethod(null, null);");
+        }
+    }
+
+    @Test
+    public void should_say_never_wanted_but_invoked() throws Exception {
+        mock.simpleMethod(1);
+
+        verify(mock, never()).simpleMethod(2);
+        try {
+            verify(mock, never()).simpleMethod(1);
+            fail();
+        } catch (NeverWantedButInvoked e) {
+            assertThat(e)
+                .hasMessageContaining("Never wanted here:")
+                .hasMessageContaining("But invoked here:");
+        }
+    }
+
+    @Test
+    public void should_show_right_actual_method() throws Exception {
+        mock.simpleMethod(9191);
+        mock.simpleMethod("foo");
+
+        try {
+            verify(mock).simpleMethod("bar");
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e)
+                .hasMessageContaining("bar")
+                .hasMessageContaining("foo");
+        }
+    }
+
+    @Mock private IMethods iHavefunkyName;
+
+    @Test
+    public void should_print_field_name_when_annotations_used() throws Exception {
+        iHavefunkyName.simpleMethod(10);
+
+        try {
+            verify(iHavefunkyName).simpleMethod(20);
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            assertThat(e)
+                .hasMessageContaining("iHavefunkyName.simpleMethod(20)")
+                .hasMessageContaining("iHavefunkyName.simpleMethod(10)");
+        }
+    }
+
+    @Test
+    public void should_print_interactions_on_mock_when_ordinary_verification_fail() throws Exception {
+        mock.otherMethod();
+        mock.booleanReturningMethod();
+
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+//            assertContains("")
+        }
+    }
+
+    @Mock private IMethods veeeeeeeeeeeeeeeeeeeeeeeerylongNameMock;
+
+    @Test
+    public void should_never_break_method_string_when_no_args_in_method() throws Exception {
+        try {
+            verify(veeeeeeeeeeeeeeeeeeeeeeeerylongNameMock).simpleMethod();
+            fail();
+        } catch(WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("veeeeeeeeeeeeeeeeeeeeeeeerylongNameMock.simpleMethod()");
+        }
+    }
+
+    @Test
+    public void should_print_method_name_and_arguments_of_other_interactions_with_different_methods() throws Exception {
+        try {
+            mock.arrayMethod(new String[] {"a", "b", "c"});
+            mock.forByte((byte) 25);
+
+            verify(mock).threeArgumentMethod(12, new Foo(), "xx");
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e)
+                .hasMessageContaining("iMethods.threeArgumentMethod(12, foo, \"xx\")")
+                .hasMessageContaining("iMethods.arrayMethod([\"a\", \"b\", \"c\"])")
+                .hasMessageContaining("iMethods.forByte((byte) 0x19)");
+        }
+    }
+
+    @Test
+    @Ignore("issue 380 related")
+    public void should_print_method_name_and_arguments_of_other_interactions_of_same_method() throws Exception {
+        try {
+            mock.forByte((byte) 25);
+            mock.forByte((byte) 12);
+
+            verify(mock).forByte((byte) 42);
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e)
+                .hasMessageContaining("iMethods.forByte(42)")
+                .hasMessageContaining("iMethods.forByte(25)")
+                .hasMessageContaining("iMethods.forByte(12)");
+        }
+    }
+
+    @Test
+    @Ignore("issue 380 related")
+    public void test1() {
+        AnInterface m = Mockito.mock(AnInterface.class);
+
+        for (int i = 1; i <= 2; i++) {
+            m.foo(i);
+        }
+
+        verify(m).foo(1);
+        verify(m).foo(2);
+        verify(m).foo(3); // XXX: doesn't mention the parameters of foo(1) and foo(2)
+        verify(m).foo(4);
+    }
+
+    @Test
+    @Ignore("issue 380 related")
+    public void test2() {
+        AnInterface m = Mockito.mock(AnInterface.class);
+
+        for (int i = 1; i <= 4; i++) {
+            m.foo(i);
+        }
+
+        verify(m).foo(1);
+        verify(m).foo(2);
+        verify(m).foo(5); // XXX: doesn't mention foo(4) at all
+    }
+
+    public interface AnInterface {
+        void foo(int i);
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/ExactNumberOfTimesVerificationTest.java b/src/test/java/org/mockitousage/verification/ExactNumberOfTimesVerificationTest.java
new file mode 100644
index 0000000..896bf74
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/ExactNumberOfTimesVerificationTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.verification.*;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class ExactNumberOfTimesVerificationTest extends TestBase {
+
+    private LinkedList<String> mock;
+
+    @Before
+    public void setup() {
+        mock = mock(LinkedList.class);
+    }
+
+    @Test
+    public void shouldDetectTooLittleActualInvocations() throws Exception {
+        mock.clear();
+        mock.clear();
+
+        verify(mock, times(2)).clear();
+        try {
+            verify(mock, times(100)).clear();
+            fail();
+        } catch (TooLittleActualInvocations e) {
+            assertThat(e)
+                .hasMessageContaining("Wanted 100 times")
+                .hasMessageContaining("was 2");
+        }
+    }
+
+    @Test
+    public void shouldDetectTooManyActualInvocations() throws Exception {
+        mock.clear();
+        mock.clear();
+
+        verify(mock, times(2)).clear();
+        try {
+            verify(mock, times(1)).clear();
+            fail();
+        } catch (TooManyActualInvocations e) {
+            assertThat(e)
+                .hasMessageContaining("Wanted 1 time")
+                .hasMessageContaining("was 2 times");
+        }
+    }
+
+    @Test
+    public void shouldDetectActualInvocationsCountIsMoreThanZero() throws Exception {
+        verify(mock, times(0)).clear();
+        try {
+            verify(mock, times(15)).clear();
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+
+    @Test
+    public void shouldDetectActuallyCalledOnce() throws Exception {
+        mock.clear();
+
+        try {
+            verify(mock, times(0)).clear();
+            fail();
+        } catch (NeverWantedButInvoked e) {
+            assertThat(e).hasMessageContaining("Never wanted here");
+        }
+    }
+
+    @Test
+    public void shouldPassWhenMethodsActuallyNotCalled() throws Exception {
+        verify(mock, times(0)).clear();
+        verify(mock, times(0)).add("yes, I wasn't called");
+    }
+
+    @Test
+    public void shouldNotCountInStubbedInvocations() throws Exception {
+        when(mock.add("test")).thenReturn(false);
+        when(mock.add("test")).thenReturn(true);
+
+        mock.add("test");
+        mock.add("test");
+
+        verify(mock, times(2)).add("test");
+    }
+
+    @Test
+    public void shouldAllowVerifyingInteractionNeverHappened() throws Exception {
+        mock.add("one");
+
+        verify(mock, never()).add("two");
+        verify(mock, never()).clear();
+
+        try {
+            verify(mock, never()).add("one");
+            fail();
+        } catch (NeverWantedButInvoked e) {}
+    }
+
+    @Test
+    public void shouldAllowVerifyingInteractionNeverHappenedInOrder() throws Exception {
+        mock.add("one");
+        mock.add("two");
+
+        InOrder inOrder = inOrder(mock);
+
+        inOrder.verify(mock, never()).add("xxx");
+        inOrder.verify(mock).add("one");
+        inOrder.verify(mock, never()).add("one");
+
+        try {
+            inOrder.verify(mock, never()).add("two");
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/FindingRedundantInvocationsInOrderTest.java b/src/test/java/org/mockitousage/verification/FindingRedundantInvocationsInOrderTest.java
new file mode 100644
index 0000000..5284c15
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/FindingRedundantInvocationsInOrderTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.UnfinishedVerificationException;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.verify;
+
+public class FindingRedundantInvocationsInOrderTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private IMethods mock2;
+
+    @Test
+    public void shouldWorkFineIfNoInvocatins() throws Exception {
+        //when
+        InOrder inOrder = inOrder(mock);
+
+        //then
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void shouldSayNoInteractionsWanted() throws Exception {
+        //when
+        mock.simpleMethod();
+
+        //then
+        InOrder inOrder = inOrder(mock);
+        try {
+            inOrder.verifyNoMoreInteractions();
+            fail();
+        } catch(VerificationInOrderFailure e) {
+            assertThat(e).hasMessageContaining("No interactions wanted");
+        }
+    }
+
+    @Test
+    public void shouldVerifyNoMoreInteractionsInOrder() throws Exception {
+        //when
+        mock.simpleMethod();
+        mock.simpleMethod(10);
+        mock.otherMethod();
+
+        //then
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).simpleMethod(10);
+        inOrder.verify(mock).otherMethod();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void shouldVerifyNoMoreInteractionsInOrderWithMultipleMocks() throws Exception {
+        //when
+        mock.simpleMethod();
+        mock2.simpleMethod();
+        mock.otherMethod();
+
+        //then
+        InOrder inOrder = inOrder(mock, mock2);
+        inOrder.verify(mock2).simpleMethod();
+        inOrder.verify(mock).otherMethod();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void shouldFailToVerifyNoMoreInteractionsInOrder() throws Exception {
+        //when
+        mock.simpleMethod();
+        mock.simpleMethod(10);
+        mock.otherMethod();
+
+        //then
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).simpleMethod(10);
+        try {
+            inOrder.verifyNoMoreInteractions();
+            fail();
+        } catch(VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldFailToVerifyNoMoreInteractionsInOrderWithMultipleMocks() throws Exception {
+        //when
+        mock.simpleMethod();
+        mock2.simpleMethod();
+        mock.otherMethod();
+
+        //then
+        InOrder inOrder = inOrder(mock, mock2);
+        inOrder.verify(mock2).simpleMethod();
+        try {
+            inOrder.verifyNoMoreInteractions();
+            fail();
+        } catch(VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldValidateState() throws Exception {
+        //when
+        InOrder inOrder = inOrder(mock);
+        verify(mock); // mess up state
+
+        //then
+        try {
+            inOrder.verifyNoMoreInteractions();
+            fail();
+        } catch(UnfinishedVerificationException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/NoMoreInteractionsVerificationTest.java b/src/test/java/org/mockitousage/verification/NoMoreInteractionsVerificationTest.java
new file mode 100644
index 0000000..6382df3
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/NoMoreInteractionsVerificationTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockitoutil.TestBase;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class NoMoreInteractionsVerificationTest extends TestBase {
+
+    private LinkedList mock;
+
+    @Before
+    public void setup() {
+        mock = mock(LinkedList.class);
+    }
+
+    @Test
+    public void shouldStubbingNotRegisterRedundantInteractions() throws Exception {
+        when(mock.add("one")).thenReturn(true);
+        when(mock.add("two")).thenReturn(true);
+
+        mock.add("one");
+
+        verify(mock).add("one");
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldVerifyWhenWantedNumberOfInvocationsUsed() throws Exception {
+        mock.add("one");
+        mock.add("one");
+        mock.add("one");
+
+        verify(mock, times(3)).add("one");
+
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldVerifyNoInteractionsAsManyTimesAsYouWant() throws Exception {
+        verifyNoMoreInteractions(mock);
+        verifyNoMoreInteractions(mock);
+
+        verifyZeroInteractions(mock);
+        verifyZeroInteractions(mock);
+    }
+
+    @Test
+    public void shouldFailZeroInteractionsVerification() throws Exception {
+        mock.clear();
+
+        try {
+            verifyZeroInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldFailNoMoreInteractionsVerification() throws Exception {
+        mock.clear();
+
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldPrintAllInvocationsWhenVerifyingNoMoreInvocations() throws Exception {
+        mock.add(1);
+        mock.add(2);
+        mock.clear();
+
+        verify(mock).add(2);
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+            assertThat(e).hasMessageContaining("list of all invocations");
+        }
+    }
+
+    @Test
+    public void shouldNotContainAllInvocationsWhenSingleUnwantedFound() throws Exception {
+        mock.add(1);
+
+        try {
+            verifyNoMoreInteractions(mock);
+            fail();
+        } catch (NoInteractionsWanted e) {
+            assertThat(e.getMessage()).doesNotContain("list of all invocations");
+        }
+    }
+
+    @Test
+    public void shouldVerifyOneMockButFailOnOther() throws Exception {
+        List<String> list = mock(List.class);
+        Map<String, Integer> map = mock(Map.class);
+
+        list.add("one");
+        list.add("one");
+
+        map.put("one", 1);
+
+        verify(list, times(2)).add("one");
+
+        verifyNoMoreInteractions(list);
+        try {
+            verifyZeroInteractions(map);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @SuppressWarnings("all")
+    @Test(expected=MockitoException.class)
+    public void verifyNoMoreInteractionsShouldScreamWhenNullPassed() throws Exception {
+        verifyNoMoreInteractions((Object[])null);
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/OnlyVerificationTest.java b/src/test/java/org/mockitousage/verification/OnlyVerificationTest.java
new file mode 100644
index 0000000..e1a5242
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/OnlyVerificationTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitoutil.TestBase;
+
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.only;
+import static org.mockito.Mockito.verify;
+
+public class OnlyVerificationTest extends TestBase {
+
+    @Mock private List<Object> mock;
+
+    @Mock private List<Object> mock2;
+
+    @Test
+    public void shouldVerifyMethodWasInvokedExclusively() {
+        mock.clear();
+        verify(mock, only()).clear();
+    }
+
+    @Test
+    public void shouldVerifyMethodWasInvokedExclusivelyWithMatchersUsage() {
+        mock.get(0);
+        verify(mock, only()).get(anyInt());
+    }
+
+    @Test
+    public void shouldFailIfMethodWasNotInvoked() {
+        mock.clear();
+        try {
+            verify(mock, only()).get(0);
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+
+    @Test
+    public void shouldFailIfMethodWasInvokedMoreThanOnce() {
+        mock.clear();
+        mock.clear();
+        try {
+            verify(mock, only()).clear();
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldFailIfMethodWasInvokedButWithDifferentArguments() {
+        mock.get(0);
+        mock.get(2);
+        try {
+            verify(mock, only()).get(999);
+            fail();
+        } catch (WantedButNotInvoked e) {}
+    }
+
+    @Test
+    public void shouldFailIfExtraMethodWithDifferentArgsFound() {
+        mock.get(0);
+        mock.get(2);
+        try {
+            verify(mock, only()).get(2);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldVerifyMethodWasInvokedExclusivelyWhenTwoMocksInUse() {
+        mock.clear();
+        mock2.get(0);
+        verify(mock, only()).clear();
+        verify(mock2, only()).get(0);
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/verification/OrdinaryVerificationPrintsAllInteractionsTest.java b/src/test/java/org/mockitousage/verification/OrdinaryVerificationPrintsAllInteractionsTest.java
new file mode 100644
index 0000000..1453e56
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/OrdinaryVerificationPrintsAllInteractionsTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+
+public class OrdinaryVerificationPrintsAllInteractionsTest extends TestBase {
+
+    @Mock private IMethods mock;
+    @Mock private IMethods mockTwo;
+
+    @Test
+    public void shouldShowAllInteractionsOnMockWhenOrdinaryVerificationFail() throws Exception {
+        //given
+        firstInteraction();
+        secondInteraction();
+
+        verify(mock).otherMethod(); //verify 1st interaction
+        try {
+            //when
+            verify(mock).simpleMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            //then
+            assertThat(e)
+                .hasMessageContaining("However, there were exactly 2 interactions with this mock")
+                .hasMessageContaining("firstInteraction(")
+                .hasMessageContaining("secondInteraction(");
+        }
+    }
+
+    @Test
+    public void shouldNotShowAllInteractionsOnDifferentMock() throws Exception {
+        differentMockInteraction();
+        firstInteraction();
+
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e.getMessage()).contains("firstInteraction(").doesNotContain("differentMockInteraction(");
+        }
+    }
+
+    @Test
+    public void shouldNotShowAllInteractionsHeaderWhenNoOtherInteractions() throws Exception {
+        try {
+            verify(mock).simpleMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("there were zero interactions with this mock.");
+        }
+    }
+
+    private void differentMockInteraction() {
+        mockTwo.simpleMethod();
+    }
+
+    private void secondInteraction() {
+        mock.booleanReturningMethod();
+    }
+
+    private void firstInteraction() {
+        mock.otherMethod();
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/PrintingVerboseTypesWithArgumentsTest.java b/src/test/java/org/mockitousage/verification/PrintingVerboseTypesWithArgumentsTest.java
new file mode 100644
index 0000000..c7e2793
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/PrintingVerboseTypesWithArgumentsTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class PrintingVerboseTypesWithArgumentsTest extends TestBase {
+
+    class Boo {
+        public void withLong(long x) {
+        }
+
+        public void withLongAndInt(long x, int y) {
+        }
+    }
+
+    @Test
+    public void should_not_report_argument_types_when_to_string_is_the_same() {
+        //given
+        Boo boo = mock(Boo.class);
+        boo.withLong(100);
+
+        try {
+            //when
+            verify(boo).withLong(eq(100));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            //then
+            assertThat(e)
+                .hasMessageContaining("withLong((Integer) 100);")
+                .hasMessageContaining("withLong((Long) 100L);");
+        }
+    }
+
+    @Test
+    public void should_show_the_type_of_only_the_argument_that_doesnt_match() {
+        //given
+        Boo boo = mock(Boo.class);
+        boo.withLongAndInt(100, 200);
+
+        try {
+            //when
+            verify(boo).withLongAndInt(eq(100), eq(200));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            //then
+            assertThat(e)
+                .hasMessageContaining("withLongAndInt((Integer) 100, 200)")
+                .hasMessageContaining("withLongAndInt((Long) 100L, 200)");
+        }
+    }
+
+    @Test
+    public void should_show_the_type_of_the_mismatching_argument_when_output_descriptions_for_invocations_are_different() {
+        //given
+        Boo boo = mock(Boo.class);
+        boo.withLongAndInt(100, 200);
+
+        try {
+            //when
+            verify(boo).withLongAndInt(eq(100), any(Integer.class));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            //then
+            Assertions.assertThat(e.getMessage())
+                      .contains("withLongAndInt(\n" +
+                                        "    (Long) 100L,\n" +
+                                        "    200\n" +
+                                        ")")
+                      .contains("withLongAndInt(\n" +
+                                        "    (Integer) 100,\n" +
+                                        "    <any java.lang.Integer>\n" +
+                                        ")");
+        }
+    }
+
+    @Test
+    public void should_not_show_types_when_argument_value_is_different() {
+        //given
+        Boo boo = mock(Boo.class);
+        boo.withLongAndInt(100, 200);
+
+        try {
+            //when
+            verify(boo).withLongAndInt(eq(100L), eq(230));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            //then
+            assertThat(e)
+                .hasMessageContaining("withLongAndInt(100L, 200)")
+                .hasMessageContaining("withLongAndInt(100L, 230)");
+        }
+    }
+
+    class Foo {
+
+        private final int x;
+
+        public Foo(int x) {
+            this.x = x;
+        }
+
+        public boolean equals(Object obj) {
+            return x == ((Foo) obj).x;
+        }
+
+        public int hashCode() {
+            return 1;
+        }
+
+        public String toString() {
+            return "foo";
+        }
+    }
+
+    @Test
+    public void should_not_show_types_when_types_are_the_same_even_if_to_string_gives_the_same_result() {
+        //given
+        IMethods mock = mock(IMethods.class);
+        mock.simpleMethod(new Foo(10));
+
+        try {
+            //when
+            verify(mock).simpleMethod(new Foo(20));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+            //then
+            assertThat(e).hasMessageContaining("simpleMethod(foo)");
+        }
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/RelaxedVerificationInOrderTest.java b/src/test/java/org/mockitousage/verification/RelaxedVerificationInOrderTest.java
new file mode 100644
index 0000000..f8144cb
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/RelaxedVerificationInOrderTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.verification.NeverWantedButInvoked;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+/**
+ * ignored since 'relaxed' in order verification is not implemented (too complex to bother, maybe later).
+ */
+public class RelaxedVerificationInOrderTest extends TestBase {
+
+    private IMethods mockOne;
+    private IMethods mockTwo;
+    private IMethods mockThree;
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() {
+        mockOne = mock(IMethods.class);
+        mockTwo = mock(IMethods.class);
+        mockThree = mock(IMethods.class);
+
+        inOrder = inOrder(mockOne, mockTwo, mockThree);
+
+        mockOne.simpleMethod(1);
+        mockTwo.simpleMethod(2);
+        mockTwo.simpleMethod(2);
+        mockThree.simpleMethod(3);
+        mockTwo.simpleMethod(2);
+        mockOne.simpleMethod(4);
+    }
+
+    @Test
+    public void shouldVerifyInOrderAllInvocations() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderAndBeRelaxed() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+
+        verifyNoMoreInteractions(mockThree);
+    }
+
+    @Test
+    public void shouldAllowFirstChunkBeforeLastInvocation() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+
+        try {
+            verifyNoMoreInteractions(mockTwo);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldAllowAllChunksBeforeLastInvocation() {
+        inOrder.verify(mockTwo, times(3)).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldVerifyDetectFirstChunkOfInvocationThatExistInManyChunks() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        try {
+            verifyNoMoreInteractions(mockTwo);
+            fail();
+        } catch(NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldVerifyDetectAllChunksOfInvocationThatExistInManyChunks() {
+        inOrder.verify(mockTwo, times(3)).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldVerifyInteractionsFromAllChunksWhenAtLeastOnceMode() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo);
+        try {
+            inOrder.verify(mockThree).simpleMethod(3);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldVerifyInteractionsFromFirstChunk() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        try {
+            verifyNoMoreInteractions(mockTwo);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test(expected=VerificationInOrderFailure.class)
+    public void shouldFailVerificationOfNonFirstChunk() {
+        inOrder.verify(mockTwo, times(1)).simpleMethod(2);
+    }
+
+    @Test
+    public void shouldPassOnCombinationOfTimesAndAtLeastOnce() {
+        mockTwo.simpleMethod(2);
+
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldPassOnEdgyCombinationOfTimesAndAtLeastOnce() {
+        mockTwo.simpleMethod(2);
+        mockThree.simpleMethod(3);
+
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+
+        verifyNoMoreInteractions(mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderMockTwoAndThree() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderMockOneAndThree() {
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockOne).simpleMethod(4);
+        verifyNoMoreInteractions(mockOne, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderOnlyTwoInvocations() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+    }
+
+    @Test
+    public void shouldVerifyInOrderOnlyMockTwo() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldVerifyMockTwoCalledTwice() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+    }
+
+    @Test
+    public void shouldVerifyMockTwoCalledAtLeastOnce() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+    }
+
+    @Test(expected=WantedButNotInvoked.class)
+    public void shouldFailOnWrongMethodCalledOnMockTwo() {
+        inOrder.verify(mockTwo, atLeastOnce()).differentMethod();
+    }
+
+    @Test
+    public void shouldAllowTimesZeroButOnlyInOrder() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        inOrder.verify(mockOne, times(0)).simpleMethod(1);
+
+        try {
+            verify(mockOne, times(0)).simpleMethod(1);
+            fail();
+        } catch (NeverWantedButInvoked e) {}
+    }
+
+    @Test
+    public void shouldFailTimesZeroInOrder() {
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        try {
+            inOrder.verify(mockThree, times(0)).simpleMethod(3);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test(expected=VerificationInOrderFailure.class)
+    public void shouldFailWhenMockTwoWantedZeroTimes() {
+        inOrder.verify(mockTwo, times(0)).simpleMethod(2);
+    }
+
+    @Test
+    public void shouldVerifyLastInvocation() {
+        inOrder.verify(mockOne).simpleMethod(4);
+    }
+
+    @Test
+    public void shouldVerifySecondAndLastInvocation() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+    }
+
+    @Test
+    public void shouldVerifySecondAndLastInvocationWhenAtLeastOnceUsed() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+    }
+
+    @Test
+    public void shouldFailOnLastTwoInvocationsInWrongOrder() {
+        inOrder.verify(mockOne).simpleMethod(4);
+        try {
+            inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldFailOnLastAndFirstInWrongOrder() {
+        inOrder.verify(mockOne).simpleMethod(4);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldFailOnWrongMethodAfterLastInvocation() {
+        inOrder.verify(mockOne).simpleMethod(4);
+        try {
+            inOrder.verify(mockOne).simpleMethod(999);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/SelectedMocksInOrderVerificationTest.java b/src/test/java/org/mockitousage/verification/SelectedMocksInOrderVerificationTest.java
new file mode 100644
index 0000000..dd95a72
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/SelectedMocksInOrderVerificationTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+public class SelectedMocksInOrderVerificationTest extends TestBase {
+
+    private IMethods mockOne;
+    private IMethods mockTwo;
+    private IMethods mockThree;
+
+    @Before
+    public void setUp() {
+        mockOne = mock(IMethods.class);
+        mockTwo = mock(IMethods.class);
+        mockThree = mock(IMethods.class);
+
+        mockOne.simpleMethod(1);
+        mockTwo.simpleMethod(2);
+        mockTwo.simpleMethod(2);
+        mockThree.simpleMethod(3);
+        mockTwo.simpleMethod(2);
+        mockOne.simpleMethod(4);
+    }
+
+    @Test
+    public void shouldVerifyAllInvocationsInOrder() {
+        InOrder inOrder = inOrder(mockOne, mockTwo, mockThree);
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        inOrder.verify(mockOne).simpleMethod(4);
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderMockTwoAndThree() {
+        InOrder inOrder = inOrder(mockTwo, mockThree);
+
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyInOrderMockOneAndThree() {
+        InOrder inOrder = inOrder(mockOne, mockThree);
+
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockOne).simpleMethod(4);
+        verifyNoMoreInteractions(mockOne, mockThree);
+    }
+
+    @Test
+    public void shouldVerifyMockOneInOrder() {
+        InOrder inOrder = inOrder(mockOne);
+
+        inOrder.verify(mockOne).simpleMethod(1);
+        inOrder.verify(mockOne).simpleMethod(4);
+
+        verifyNoMoreInteractions(mockOne);
+    }
+
+    @Test
+    public void shouldFailVerificationForMockOne() {
+        InOrder inOrder = inOrder(mockOne);
+
+        inOrder.verify(mockOne).simpleMethod(1);
+        try {
+            inOrder.verify(mockOne).differentMethod();
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldFailVerificationForMockOneBecauseOfWrongOrder() {
+        InOrder inOrder = inOrder(mockOne);
+
+        inOrder.verify(mockOne).simpleMethod(4);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldVerifyMockTwoWhenThreeTimesUsed() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        inOrder.verify(mockTwo, times(3)).simpleMethod(2);
+
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldVerifyMockTwo() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(2);
+
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldFailVerificationForMockTwo() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        try {
+            inOrder.verify(mockTwo).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldThrowNoMoreInvocationsForMockTwo() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        try {
+            inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldThrowTooLittleInvocationsForMockTwo() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        try {
+            inOrder.verify(mockTwo, times(4)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldThrowTooManyInvocationsForMockTwo() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        try {
+            inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldAllowThreeTimesOnMockTwo() {
+        InOrder inOrder = inOrder(mockTwo);
+
+        inOrder.verify(mockTwo, times(3)).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo);
+    }
+
+    @Test
+    public void shouldVerifyMockTwoCompletely() {
+        InOrder inOrder = inOrder(mockTwo, mockThree);
+
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockTwo).simpleMethod(2);
+        verifyNoMoreInteractions(mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldAllowTwoTimesOnMockTwo() {
+        InOrder inOrder = inOrder(mockTwo, mockThree);
+
+        inOrder.verify(mockTwo, times(2)).simpleMethod(2);
+        try {
+            verifyNoMoreInteractions(mockTwo);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationAfterDelayTest.java b/src/test/java/org/mockitousage/verification/VerificationAfterDelayTest.java
new file mode 100644
index 0000000..f2fd3ae
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationAfterDelayTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2007 Mockito contributors This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+import org.mockitoutil.RetryRule;
+import org.mockitoutil.Stopwatch;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static junit.framework.TestCase.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.rules.ExpectedException.none;
+import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.junit.MockitoJUnit.rule;
+import static org.mockitoutil.Stopwatch.createNotStarted;
+
+public class VerificationAfterDelayTest {
+
+    @Rule
+    public MockitoRule mockito = rule();
+
+    @Rule
+    public RetryRule retryRule = RetryRule.attempts(4);
+
+    @Rule
+    public ExpectedException exception = none();
+
+    @Mock
+    private IMethods mock;
+
+    @Captor
+    private ArgumentCaptor<Character> captor;
+
+    private Stopwatch stopWatch;
+
+    private DelayedExecution delayedExecution;
+
+    private Runnable callMock = new Runnable() {
+        @Override
+        public void run() {
+            mock.oneArg('1');
+        }
+    };
+
+    @Before
+    public void setUp() {
+        delayedExecution = new DelayedExecution();
+        stopWatch = createNotStarted();
+    }
+
+    @After
+    public void tearDown() throws InterruptedException {
+        delayedExecution.close();
+    }
+
+    @Test
+    public void shouldVerifyNormallyWithSpecificTimes() throws Exception {
+        // given
+        delayedExecution.callAsync(30, MILLISECONDS, callMock );
+
+        // then
+        verify(mock, after(100).times(1)).oneArg('1');
+    }
+
+    @Test
+    public void shouldVerifyNormallyWithAtLeast() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock );
+
+        // then
+        verify(mock, after(100).atLeast(1)).oneArg('1');
+    }
+
+    @Test
+    public void shouldFailVerificationWithWrongTimes() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock );
+
+        // then
+        verify(mock, times(0)).oneArg('1');
+        exception.expect(MockitoAssertionError.class);
+        verify(mock, after(100).times(2)).oneArg('1');
+    }
+
+    @Test
+    public void shouldWaitTheFullTimeIfTheTestCouldPass() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock );
+
+        // then
+        stopWatch.start();
+
+        try {
+            verify(mock, after(100).atLeast(2)).oneArg('1');
+            Assert.fail("Expected behavior was to throw an exception, and never reach this line");
+        } catch (MockitoAssertionError ignored) {
+        }
+
+        stopWatch.assertElapsedTimeIsMoreThan(100, MILLISECONDS);
+    }
+
+    @Test
+    public void shouldStopEarlyIfTestIsDefinitelyFailed() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock );
+
+        // then
+        exception.expect(MockitoAssertionError.class);
+        verify(mock, after(10000).never()).oneArg('1');
+    }
+
+    /**
+     * Test for issue #345.
+     */
+    @Test
+    public void shouldReturnListOfArgumentsWithSameSizeAsGivenInAtMostVerification() {
+        // given
+        int n = 3;
+
+        // when
+        exerciseMockNTimes(n);
+
+        stopWatch.start();
+        // then
+        verify(mock, after(200).atMost(n)).oneArg((char) captor.capture());
+
+        stopWatch.assertElapsedTimeIsMoreThan(200, MILLISECONDS);
+        assertThat(captor.getAllValues()).containsExactly('0', '1', '2');
+    }
+
+    @Test
+    public void shouldReturnListOfArgumentsWithSameSizeAsGivenInTimesVerification() {
+        // given
+        int n = 3;
+
+        // when
+        exerciseMockNTimes(n);
+
+        //Then
+        verify(mock, after(200).times(n)).oneArg((char) captor.capture());
+        assertEquals(n, captor.getAllValues().size());
+        assertEquals('0', (char) captor.getAllValues().get(0));
+        assertEquals('1', (char) captor.getAllValues().get(1));
+        assertEquals('2', (char) captor.getAllValues().get(2));
+    }
+
+    @Test
+    public void shouldReturnListOfArgumentsWithSameSizeAsGivenInAtLeastVerification() {
+        // given
+        int n = 3;
+
+        // when
+        exerciseMockNTimes(n);
+
+        //Then
+        verify(mock, after(200).atLeast(n)).oneArg((char) captor.capture());
+        assertEquals(n, captor.getAllValues().size());
+        assertEquals('0', (char) captor.getAllValues().get(0));
+        assertEquals('1', (char) captor.getAllValues().get(1));
+        assertEquals('2', (char) captor.getAllValues().get(2));
+    }
+
+    private void exerciseMockNTimes(int n) {
+        for (int i = 0; i < n; i++) {
+            mock.oneArg((char) ('0' + i));
+        }
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationExcludingStubsTest.java b/src/test/java/org/mockitousage/verification/VerificationExcludingStubsTest.java
new file mode 100644
index 0000000..3a6b276
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationExcludingStubsTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class VerificationExcludingStubsTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    @Test
+    public void shouldAllowToExcludeStubsForVerification() throws Exception {
+        //given
+        when(mock.simpleMethod()).thenReturn("foo");
+
+        //when
+        String stubbed = mock.simpleMethod(); //irrelevant call because it is stubbing
+        mock.objectArgMethod(stubbed);
+
+        //then
+        verify(mock).objectArgMethod("foo");
+
+        //verifyNoMoreInteractions fails:
+        try { verifyNoMoreInteractions(mock); fail(); } catch (NoInteractionsWanted e) {}
+
+        //but it works when stubs are ignored:
+        ignoreStubs(mock);
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldExcludeFromVerificationInOrder() throws Exception {
+        //given
+        when(mock.simpleMethod()).thenReturn("foo");
+
+        //when
+        mock.objectArgMethod("1");
+        mock.objectArgMethod("2");
+        mock.simpleMethod(); //calling the stub
+
+        //then
+        InOrder inOrder = inOrder(ignoreStubs(mock));
+        inOrder.verify(mock).objectArgMethod("1");
+        inOrder.verify(mock).objectArgMethod("2");
+        inOrder.verifyNoMoreInteractions();
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void shouldIgnoringStubsDetectNulls() throws Exception {
+        ignoreStubs(mock, null);
+    }
+
+    @Test(expected = NotAMockException.class)
+    public void shouldIgnoringStubsDetectNonMocks() throws Exception {
+        ignoreStubs(mock, new Object());
+    }
+
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationInOrderMixedWithOrdiraryVerificationTest.java b/src/test/java/org/mockitousage/verification/VerificationInOrderMixedWithOrdiraryVerificationTest.java
new file mode 100644
index 0000000..cd31a19
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationInOrderMixedWithOrdiraryVerificationTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.*;
+import static org.mockito.Mockito.*;
+
+public class VerificationInOrderMixedWithOrdiraryVerificationTest extends TestBase {
+
+    private IMethods mockOne;
+    private IMethods mockTwo;
+    private IMethods mockThree;
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() {
+        mockOne = mock(IMethods.class);
+        mockTwo = mock(IMethods.class);
+        mockThree = mock(IMethods.class);
+
+        mockOne.simpleMethod(1);
+        mockOne.simpleMethod(1);
+        mockTwo.simpleMethod(2);
+        mockThree.simpleMethod(3);
+        mockThree.simpleMethod(4);
+
+        inOrder = inOrder(mockOne, mockThree);
+    }
+
+    @Test
+    public void shouldMixVerificationInOrderAndOrdinaryVerification() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockThree).simpleMethod(4);
+        verify(mockTwo).simpleMethod(2);
+
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldAllowOrdinarilyVerifyingMockPassedToInOrderObject() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+
+        verify(mockThree).simpleMethod(3);
+        verify(mockThree).simpleMethod(4);
+        verify(mockTwo).simpleMethod(2);
+
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldAllowRedundantVerifications() {
+        verify(mockOne, atLeastOnce()).simpleMethod(1);
+        verify(mockTwo).simpleMethod(2);
+        verify(mockThree).simpleMethod(3);
+        verify(mockThree).simpleMethod(4);
+
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockThree).simpleMethod(4);
+
+        verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldFailOnNoMoreInteractions() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockThree).simpleMethod(3);
+        inOrder.verify(mockThree).simpleMethod(4);
+
+        try {
+            verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldFailOnNoMoreInteractionsOnMockVerifiedInOrder() {
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+        inOrder.verify(mockThree).simpleMethod(3);
+        verify(mockTwo).simpleMethod(2);
+
+        try {
+            verifyNoMoreInteractions(mockOne, mockTwo, mockThree);
+            fail();
+        } catch (NoInteractionsWanted e) {}
+    }
+
+    @Test
+    public void shouldAllowOneMethodVerifiedInOrder() {
+        verify(mockTwo).simpleMethod(2);
+        verify(mockOne, atLeastOnce()).simpleMethod(1);
+
+        inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+    }
+
+    @Test
+    public void shouldFailOnLastInvocationTooEarly() {
+        inOrder.verify(mockThree).simpleMethod(4);
+
+        verify(mockThree).simpleMethod(4);
+        verify(mockTwo).simpleMethod(2);
+
+        try {
+            inOrder.verify(mockOne, atLeastOnce()).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test(expected=MockitoException.class)
+    public void shouldScreamWhenUnfamiliarMockPassedToInOrderObject() {
+        inOrder.verify(mockTwo, atLeastOnce()).simpleMethod(1);
+    }
+
+    @Test
+    public void shouldUseEqualsToVerifyMethodArguments() {
+        mockOne = mock(IMethods.class);
+
+        String textOne = "test";
+        String textTwo = new String(textOne);
+
+        assertEquals(textOne, textTwo);
+        assertNotSame(textOne, textTwo);
+
+        mockOne.simpleMethod(textOne);
+        mockOne.simpleMethod(textTwo);
+
+        verify(mockOne, times(2)).simpleMethod(textOne);
+
+        inOrder = inOrder(mockOne);
+        inOrder.verify(mockOne, times(2)).simpleMethod(textOne);
+    }
+
+    @Test
+    public void shouldUseEqualsToVerifyMethodVarargs() {
+        mockOne = mock(IMethods.class);
+
+        String textOne = "test";
+        String textTwo = new String(textOne);
+
+        assertEquals(textOne, textTwo);
+        assertNotSame(textOne, textTwo);
+
+        mockOne.varargsObject(1, textOne, textOne);
+        mockOne.varargsObject(1, textTwo, textTwo);
+
+        verify(mockOne, times(2)).varargsObject(1, textOne, textOne);
+
+        inOrder = inOrder(mockOne);
+        inOrder.verify(mockOne, times(2)).varargsObject(1, textOne, textOne);
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationInOrderTest.java b/src/test/java/org/mockitousage/verification/VerificationInOrderTest.java
new file mode 100644
index 0000000..5d75299
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationInOrderTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.fail;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class VerificationInOrderTest extends TestBase {
+
+    private IMethods mockOne;
+    private IMethods mockTwo;
+    private IMethods mockThree;
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() {
+        mockOne = mock(IMethods.class);
+        mockTwo = mock(IMethods.class);
+        mockThree = mock(IMethods.class);
+
+        inOrder = inOrder(mockOne, mockTwo, mockThree);
+    }
+
+    @Test
+    public void shouldVerifySingleMockInOrderAndNotInOrder() {
+        mockOne = mock(IMethods.class);
+        inOrder = inOrder(mockOne);
+
+        mockOne.simpleMethod(1);
+        mockOne.simpleMethod(2);
+
+        verify(mockOne).simpleMethod(2);
+        verify(mockOne).simpleMethod(1);
+
+        inOrder.verify(mockOne).simpleMethod(2);
+        try {
+            inOrder.verify(mockOne).simpleMethod(1);
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldMessagesPointToProperMethod() {
+        mockTwo.differentMethod();
+        mockOne.simpleMethod();
+
+        try {
+            inOrder.verify(mockOne, atLeastOnce()).differentMethod();
+            fail();
+        } catch (WantedButNotInvoked e) {
+            assertThat(e).hasMessageContaining("differentMethod()");
+        }
+    }
+
+    @Test
+    public void shouldVerifyInOrderWhenTwoChunksAreEqual() {
+        mockOne.simpleMethod();
+        mockOne.simpleMethod();
+        mockTwo.differentMethod();
+        mockOne.simpleMethod();
+        mockOne.simpleMethod();
+
+        inOrder.verify(mockOne, times(2)).simpleMethod();
+        inOrder.verify(mockTwo).differentMethod();
+        inOrder.verify(mockOne, times(2)).simpleMethod();
+        try {
+            inOrder.verify(mockOne, atLeastOnce()).simpleMethod();
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+
+    @Test
+    public void shouldVerifyInOrderUsingMatcher() {
+        mockOne.simpleMethod(1);
+        mockOne.simpleMethod(2);
+        mockTwo.differentMethod();
+        mockOne.simpleMethod(3);
+        mockOne.simpleMethod(4);
+
+        verify(mockOne, times(4)).simpleMethod(anyInt());
+
+        inOrder.verify(mockOne, times(2)).simpleMethod(anyInt());
+        inOrder.verify(mockTwo).differentMethod();
+        inOrder.verify(mockOne, times(2)).simpleMethod(anyInt());
+        try {
+            inOrder.verify(mockOne, times(3)).simpleMethod(anyInt());
+            fail();
+        } catch (VerificationInOrderFailure e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationInOrderWithCallsTest.java b/src/test/java/org/mockitousage/verification/VerificationInOrderWithCallsTest.java
new file mode 100644
index 0000000..4c52b34
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationInOrderWithCallsTest.java
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.verification;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.mockito.Mockito.*;
+
+public class VerificationInOrderWithCallsTest extends TestBase {
+
+    @Mock private IMethods mockOne;
+    @Mock private IMethods mockTwo;
+    @Rule
+    public ExpectedException exceptionRule = ExpectedException.none();
+
+    @Test
+    public void shouldFailWhenMethodNotCalled(){
+        // Given
+        mockOne.oneArg( 1 );
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "Verification in order failure" );
+        exceptionRule.expectMessage( "Wanted but not invoked" );
+        exceptionRule.expectMessage( "mockOne.oneArg(2)" );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 2 );
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldFailWhenMethodCalledTooFewTimes(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "Verification in order failure" );
+        exceptionRule.expectMessage( "mockOne.oneArg(2)" );
+        exceptionRule.expectMessage( "Wanted 2 times" );
+        exceptionRule.expectMessage( "But was 1 time" );
+
+        // When
+        verifier.verify( mockOne, calls(2)).oneArg( 2 );
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldFailWhenSingleMethodCallsAreOutOfSequence(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 2 );
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "Verification in order failure" );
+        exceptionRule.expectMessage( "Wanted but not invoked" );
+        exceptionRule.expectMessage( "mockOne.oneArg(1)" );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldFailWhenDifferentMethodCallsAreOutOfSequence(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.voidMethod();
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "Verification in order failure" );
+        exceptionRule.expectMessage( "Wanted but not invoked" );
+        exceptionRule.expectMessage( "mockOne.oneArg(1)" );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldFailWhenMethodCallsOnDifferentMocksAreOutOfSequence(){
+        // Given
+        mockOne.voidMethod();
+        mockTwo.voidMethod();
+
+        InOrder verifier = inOrder( mockOne, mockTwo );
+        verifier.verify( mockTwo, calls(1)).voidMethod();
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "Verification in order failure" );
+        exceptionRule.expectMessage( "Wanted but not invoked" );
+        exceptionRule.expectMessage( "mockOne.voidMethod()" );
+
+        // When
+        verifier.verify( mockOne, calls(1)).voidMethod();
+
+        // Then - expected exception thrown
+    }
+
+
+    @Test
+    public void shouldAllowSequentialCallsToCallsForSingleMethod(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(2)).oneArg( 2 );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifyNoMoreInteractions(mockOne);
+        verifier.verifyNoMoreInteractions();
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldAllowSequentialCallsToCallsForDifferentMethods(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.voidMethod();
+        mockOne.voidMethod();
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(2)).voidMethod();
+        verifier.verify( mockOne, calls(1)).oneArg(1);
+        verifyNoMoreInteractions(mockOne);
+        verifier.verifyNoMoreInteractions();
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldAllowSequentialCallsToCallsForMethodsOnDifferentMocks(){
+        // Given
+        mockOne.voidMethod();
+        mockTwo.voidMethod();
+        mockTwo.voidMethod();
+        mockOne.voidMethod();
+
+        InOrder verifier = inOrder( mockOne, mockTwo );
+
+        // When
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockTwo, calls(2)).voidMethod();
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifyNoMoreInteractions(mockOne);
+        verifyNoMoreInteractions(mockTwo);
+        verifier.verifyNoMoreInteractions();
+
+        // Then - no exception thrown
+    }
+
+
+    @Test
+    public void shouldAllowFewerCallsForSingleMethod(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).oneArg( 2 );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).oneArg( 2 );
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldNotVerifySkippedCallsWhenFewerCallsForSingleMethod(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).oneArg( 2 );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        exceptionRule.expect( NoInteractionsWanted.class );
+
+        // When
+        verifyNoMoreInteractions( mockOne );
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldNotVerifySkippedCallsInInOrderWhenFewerCallsForSingleMethod(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).oneArg( 2 );
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "No interactions wanted here" );
+
+        // When
+        verifier.verifyNoMoreInteractions();
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldAllowFewerCallsForDifferentMethods(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.voidMethod();
+        mockOne.voidMethod();
+        mockOne.oneArg( 1 );
+        mockOne.voidMethod();
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldNotVerifySkippedCallsWhenFewerCallsForDifferentMethods(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.voidMethod();
+        mockOne.voidMethod();
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        exceptionRule.expect( NoInteractionsWanted.class );
+
+        // When
+        verifyNoMoreInteractions( mockOne );
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldNotVerifySkippedCallsInInOrderWhenFewerCallsForDifferentMethods(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.voidMethod();
+        mockOne.voidMethod();
+
+        InOrder verifier = inOrder( mockOne );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "No interactions wanted here" );
+
+        // When
+        verifier.verifyNoMoreInteractions();
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldAllowFewerCallsForMethodsOnDifferentMocks(){
+        // Given
+        mockOne.voidMethod();
+        mockTwo.voidMethod();
+        mockTwo.voidMethod();
+        mockOne.voidMethod();
+        mockTwo.voidMethod();
+
+        InOrder verifier = inOrder( mockOne, mockTwo );
+
+        // When
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockTwo, calls(1)).voidMethod();
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockTwo, calls(1)).voidMethod();
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldNotVerifySkippedCallsWhenFewerCallsForMethodsOnDifferentMocks(){
+        // Given
+        mockOne.voidMethod();
+        mockTwo.voidMethod();
+        mockTwo.voidMethod();
+        mockOne.voidMethod();
+
+        InOrder verifier = inOrder( mockOne, mockTwo );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockTwo, calls(1)).voidMethod();
+        verifier.verify( mockOne, calls(1)).voidMethod();
+
+        exceptionRule.expect(NoInteractionsWanted.class);
+
+        // When
+        verifyNoMoreInteractions( mockTwo );
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldNotVerifySkippedCallsInInOrderWhenFewerCallsForMethodsOnDifferentMocks(){
+        // Given
+        mockOne.voidMethod();
+        mockTwo.voidMethod();
+        mockTwo.voidMethod();
+
+        InOrder verifier = inOrder( mockOne, mockTwo );
+        verifier.verify( mockOne, calls(1)).voidMethod();
+        verifier.verify( mockTwo, calls(1)).voidMethod();
+
+        exceptionRule.expect( VerificationInOrderFailure.class );
+        exceptionRule.expectMessage( "No interactions wanted here" );
+
+        // When
+        verifier.verifyNoMoreInteractions();
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldVerifyWithCallsAfterUseOfTimes(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, times(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(2)).oneArg( 2 );
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldVerifyWithCallsAfterUseOfAtLeast(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, atLeast(1)).oneArg( 1 );
+        verifier.verify( mockOne, calls(2)).oneArg( 2 );
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldVerifyWithTimesAfterUseOfCalls(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, times(2)).oneArg( 2 );
+        verifier.verify( mockOne, times(1)).oneArg( 1 );
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldVerifyWithAtLeastAfterUseOfCalls(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 2 );
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, atLeast(1)).oneArg( 2 );
+        verifier.verify( mockOne, atLeast(1)).oneArg( 1 );
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldVerifyWithTimesAfterCallsInSameChunk(){
+        // Given
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 1 );
+        mockOne.oneArg( 1 );
+
+        InOrder verifier = inOrder( mockOne );
+
+        // When
+        verifier.verify( mockOne, calls(1)).oneArg( 1 );
+        verifier.verify( mockOne, times(2)).oneArg( 1 );
+        verifier.verifyNoMoreInteractions();
+
+        // Then - no exception thrown
+    }
+
+    @Test
+    public void shouldFailToCreateCallsWithZeroArgument(){
+        // Given
+        InOrder verifier = inOrder( mockOne );
+        exceptionRule.expect( MockitoException.class );
+        exceptionRule.expectMessage( "Negative and zero values are not allowed here" );
+
+        // When
+        verifier.verify( mockOne, calls(0)).voidMethod();
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldFailToCreateCallsWithNegativeArgument(){
+        // Given
+        InOrder verifier = inOrder( mockOne );
+        exceptionRule.expect( MockitoException.class );
+        exceptionRule.expectMessage( "Negative and zero values are not allowed here" );
+
+        // When
+        verifier.verify( mockOne, calls(-1)).voidMethod();
+
+        // Then - expected exception thrown
+    }
+
+    @Test
+    public void shouldFailToCreateCallsForNonInOrderVerification(){
+        // Given
+        mockOne.voidMethod();
+        exceptionRule.expect( MockitoException.class );
+        exceptionRule.expectMessage( "calls is only intended to work with InOrder" );
+
+        // When
+        verify( mockOne, calls(1)).voidMethod();
+
+        // Then - expected exception thrown
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationOnMultipleMocksUsingMatchersTest.java b/src/test/java/org/mockitousage/verification/VerificationOnMultipleMocksUsingMatchersTest.java
new file mode 100644
index 0000000..45bf19d
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationOnMultipleMocksUsingMatchersTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockitoutil.TestBase;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.mockito.Mockito.*;
+
+@SuppressWarnings("unchecked")
+public class VerificationOnMultipleMocksUsingMatchersTest extends TestBase {
+
+    @Test
+    public void shouldVerifyUsingMatchers() throws Exception {
+        List<Object> list = Mockito.mock(List.class);
+        HashMap<Object, Object> map = Mockito.mock(HashMap.class);
+
+        list.add("test");
+        list.add(1, "test two");
+
+        map.put("test", 100);
+        map.put("test two", 200);
+
+        verify(list).add(anyObject());
+        verify(list).add(anyInt(), eq("test two"));
+
+        verify(map, times(2)).put(anyObject(), anyObject());
+        verify(map).put(eq("test two"), eq(200));
+
+        verifyNoMoreInteractions(list, map);
+    }
+
+    @Test
+    public void shouldVerifyMultipleMocks() throws Exception {
+        List<String> list = mock(List.class);
+        Map<Object, Integer> map = mock(Map.class);
+        Set<?> set = mock(Set.class);
+
+        list.add("one");
+        list.add("one");
+        list.add("two");
+
+        map.put("one", 1);
+        map.put("one", 1);
+
+        verify(list, times(2)).add("one");
+        verify(list, times(1)).add("two");
+        verify(list, times(0)).add("three");
+
+        verify(map, times(2)).put(anyObject(), anyInt());
+
+        verifyNoMoreInteractions(list, map);
+        verifyZeroInteractions(set);
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationUsingMatchersTest.java b/src/test/java/org/mockitousage/verification/VerificationUsingMatchersTest.java
new file mode 100644
index 0000000..c89b751
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationUsingMatchersTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.mockito.exceptions.verification.WantedButNotInvoked;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotSame;
+import static junit.framework.TestCase.fail;
+import static org.mockito.AdditionalMatchers.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class VerificationUsingMatchersTest extends TestBase {
+
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = Mockito.mock(IMethods.class);
+    }
+
+    @Test
+    public void shouldVerifyExactNumberOfInvocationsUsingMatcher() {
+        mock.simpleMethod(1);
+        mock.simpleMethod(2);
+        mock.simpleMethod(3);
+
+        verify(mock, times(3)).simpleMethod(anyInt());
+    }
+
+    @Test
+    public void shouldVerifyUsingSameMatcher() {
+        Object one = new String("1243");
+        Object two = new String("1243");
+        Object three = new String("1243");
+
+        assertNotSame(one, two);
+        assertEquals(one, two);
+        assertEquals(two, three);
+
+        mock.oneArg(one);
+        mock.oneArg(two);
+
+        verify(mock).oneArg(same(one));
+        verify(mock, times(2)).oneArg(two);
+
+        try {
+            verify(mock).oneArg(same(three));
+            fail();
+        } catch (WantedButNotInvoked e) {
+        }
+    }
+
+    @Test
+    public void shouldVerifyUsingMixedMatchers() {
+        mock.threeArgumentMethod(11, "", "01234");
+
+        try {
+            verify(mock).threeArgumentMethod(and(geq(7), leq(10)), isA(String.class), Matchers.contains("123"));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+        }
+
+        mock.threeArgumentMethod(8, new Object(), "01234");
+
+        try {
+            verify(mock).threeArgumentMethod(and(geq(7), leq(10)), isA(String.class), Matchers.contains("123"));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+        }
+
+        mock.threeArgumentMethod(8, "", "no match");
+
+        try {
+            verify(mock).threeArgumentMethod(and(geq(7), leq(10)), isA(String.class), Matchers.contains("123"));
+            fail();
+        } catch (ArgumentsAreDifferent e) {
+        }
+
+        mock.threeArgumentMethod(8, "", "123");
+
+        verify(mock).threeArgumentMethod(and(geq(7), leq(10)), isA(String.class), Matchers.contains("123"));
+    }
+}
diff --git a/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java b/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java
new file mode 100644
index 0000000..798e0e8
--- /dev/null
+++ b/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitousage.verification;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.junit.MockitoRule;
+import org.mockitousage.IMethods;
+import org.mockitoutil.RetryRule;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.junit.rules.ExpectedException.none;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.junit.MockitoJUnit.rule;
+
+public class VerificationWithTimeoutTest {
+
+    @Rule
+    public MockitoRule mockito = rule();
+
+    @Rule
+    public RetryRule retryRule = RetryRule.attempts(4);
+
+    @Rule
+    public ExpectedException exception = none();
+
+    @Mock
+    private IMethods mock;
+
+    private DelayedExecution delayedExecution;
+
+    @Before
+    public void setUp() {
+        delayedExecution = new DelayedExecution();
+    }
+
+    @After
+    public void tearDown() throws InterruptedException {
+        delayedExecution.close();
+    }
+
+    @Test
+    public void shouldVerifyWithTimeout() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock('c'));
+
+        // then
+        verify(mock, timeout(100)).oneArg('c');
+        verify(mock, timeout(100).atLeastOnce()).oneArg('c');
+        verify(mock, timeout(100).times(1)).oneArg('c');
+        verify(mock).oneArg('c');
+        verify(mock, times(1)).oneArg('c');
+    }
+
+    @Test
+    public void shouldFailVerificationWithTimeout() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock('c'));
+
+        // then
+        verify(mock, never()).oneArg('c');
+        exception.expect(MockitoAssertionError.class);
+        verify(mock, timeout(20).atLeastOnce()).oneArg('c');
+    }
+
+    @Test
+    public void shouldAllowMixingOtherModesWithTimeout() throws Exception {
+        // when
+        delayedExecution.callAsync(10, MILLISECONDS, callMock('c'));
+        delayedExecution.callAsync(10, MILLISECONDS, callMock('c'));
+
+        // then
+        verify(mock, timeout(100).atLeast(1)).oneArg('c');
+        verify(mock, timeout(100).times(2)).oneArg('c');
+        verifyNoMoreInteractions(mock);
+    }
+
+    @Test
+    public void shouldAllowMixingOtherModesWithTimeoutAndFail() throws Exception {
+        // when
+        delayedExecution.callAsync(10, MILLISECONDS, callMock('c'));
+        delayedExecution.callAsync(10, MILLISECONDS, callMock('c'));
+
+        // then
+        verify(mock, timeout(100).atLeast(1)).oneArg('c');
+        exception.expect(TooLittleActualInvocations.class);
+        verify(mock, timeout(100).times(3)).oneArg('c');
+    }
+
+    @Test
+    public void shouldAllowMixingOnlyWithTimeout() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock('c'));
+
+        // then
+        verify(mock, never()).oneArg('c');
+        verify(mock, timeout(100).only()).oneArg('c');
+    }
+
+    @Test
+    public void shouldAllowMixingOnlyWithTimeoutAndFail() throws Exception {
+        // when
+        delayedExecution.callAsync(30, MILLISECONDS, callMock('c'));
+
+        // and when
+        mock.oneArg('x');
+
+        // then
+        verify(mock, never()).oneArg('c');
+        exception.expect(NoInteractionsWanted.class);
+        verify(mock, timeout(100).only()).oneArg('c');
+    }
+
+    /**
+     * This test is JUnit-specific because the code behaves different if JUnit
+     * is used.
+     */
+    @Test
+    public void canIgnoreInvocationsWithJunit() throws InterruptedException {
+        // when
+        delayedExecution.callAsync(10, MILLISECONDS, callMock('1'));
+
+        // then
+        verify(mock, timeout(50)).oneArg('1');
+
+        // when
+        delayedExecution.callAsync(10, MILLISECONDS, callMock('2'));
+        delayedExecution.callAsync(20, MILLISECONDS, callMock('3'));
+
+        // then
+        verify(mock, timeout(50)).oneArg('3');
+    }
+
+    @Test
+    public void shouldAllowTimeoutVerificationInOrder() throws Exception {
+        // when
+        delayedExecution.callAsync(50, MILLISECONDS, callMock('1'));
+
+        // and when
+        mock.oneArg('x');
+
+        // then
+        InOrder inOrder = inOrder(mock);
+        inOrder.verify(mock).oneArg('x');
+        inOrder.verify(mock, never()).oneArg('1');
+        inOrder.verify(mock, timeout(100)).oneArg('1');
+    }
+
+    private Runnable callMock(final char c) {
+        return new Runnable() {
+            @Override
+            public void run() {
+                mock.oneArg(c);
+            }
+        };
+    }
+}
diff --git a/src/test/java/org/mockitoutil/Assertor.java b/src/test/java/org/mockitoutil/Assertor.java
new file mode 100644
index 0000000..9ac1763
--- /dev/null
+++ b/src/test/java/org/mockitoutil/Assertor.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitoutil;
+
+public interface Assertor<T> {
+
+    void assertValue(T value);
+}
diff --git a/src/test/java/org/mockitoutil/ClassLoaders.java b/src/test/java/org/mockitoutil/ClassLoaders.java
new file mode 100644
index 0000000..506f0eb
--- /dev/null
+++ b/src/test/java/org/mockitoutil/ClassLoaders.java
@@ -0,0 +1,526 @@
+package org.mockitoutil;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+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.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import org.objenesis.Objenesis;
+import org.objenesis.ObjenesisStd;
+import org.objenesis.instantiator.ObjectInstantiator;
+
+import static java.lang.String.format;
+import static java.util.Arrays.asList;
+
+public abstract class ClassLoaders {
+    protected ClassLoader parent = currentClassLoader();
+
+    protected ClassLoaders() {
+    }
+
+    public static IsolatedURLClassLoaderBuilder isolatedClassLoader() {
+        return new IsolatedURLClassLoaderBuilder();
+    }
+
+    public static ExcludingURLClassLoaderBuilder excludingClassLoader() {
+        return new ExcludingURLClassLoaderBuilder();
+    }
+
+    public static InMemoryClassLoaderBuilder inMemoryClassLoader() {
+        return new InMemoryClassLoaderBuilder();
+    }
+
+    public static ReachableClassesFinder in(ClassLoader classLoader) {
+        return new ReachableClassesFinder(classLoader);
+    }
+
+    public static ClassLoader jdkClassLoader() {
+        return String.class.getClassLoader();
+    }
+
+    public static ClassLoader systemClassLoader() {
+        return ClassLoader.getSystemClassLoader();
+    }
+
+    public static ClassLoader currentClassLoader() {
+        return ClassLoaders.class.getClassLoader();
+    }
+
+    public abstract ClassLoader build();
+
+    public static Class<?>[] coverageTool() {
+        HashSet<Class<?>> classes = new HashSet<Class<?>>();
+        classes.add(safeGetClass("net.sourceforge.cobertura.coveragedata.TouchCollector"));
+        classes.add(safeGetClass("org.slf4j.LoggerFactory"));
+
+        classes.remove(null);
+        return classes.toArray(new Class<?>[classes.size()]);
+    }
+
+    private static Class<?> safeGetClass(String className) {
+        try {
+            return Class.forName(className);
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    public static ClassLoaderExecutor using(final ClassLoader classLoader) {
+        return new ClassLoaderExecutor(classLoader);
+    }
+
+    public static class ClassLoaderExecutor {
+        private ClassLoader classLoader;
+
+        public ClassLoaderExecutor(ClassLoader classLoader) {
+            this.classLoader = classLoader;
+        }
+
+        public void execute(final Runnable task) throws Exception {
+            ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
+                @Override
+                public Thread newThread(Runnable r) {
+                    Thread thread = Executors.defaultThreadFactory().newThread(r);
+                    thread.setContextClassLoader(classLoader);
+                    return thread;
+                }
+            });
+            try {
+                Future<?> taskFuture = executorService.submit(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            reloadTaskInClassLoader(task).run();
+                        } catch (Throwable throwable) {
+                            throw new IllegalStateException(format("Given task could not be loaded properly in the given classloader '%s', error '%s",
+                                                                   task,
+                                                                   throwable.getMessage()),
+                                                            throwable);
+                        }
+                    }
+                });
+                taskFuture.get();
+                executorService.shutdownNow();
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            } catch (ExecutionException e) {
+                throw this.<Exception>unwrapAndThrows(e);
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        private <T extends Throwable> T unwrapAndThrows(ExecutionException ex) throws T {
+            throw (T) ex.getCause();
+        }
+
+        Runnable reloadTaskInClassLoader(Runnable task) {
+            try {
+                @SuppressWarnings("unchecked")
+                Class<Runnable> taskClassReloaded = (Class<Runnable>) classLoader.loadClass(task.getClass().getName());
+
+                Objenesis objenesis = new ObjenesisStd();
+                ObjectInstantiator<Runnable> thingyInstantiator = objenesis.getInstantiatorOf(taskClassReloaded);
+                Runnable reloaded = thingyInstantiator.newInstance();
+
+                // lenient shallow copy of class compatible fields
+                for (Field field : task.getClass().getDeclaredFields()) {
+                    Field declaredField = taskClassReloaded.getDeclaredField(field.getName());
+                    int modifiers = declaredField.getModifiers();
+                    if(Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
+                        // Skip static final fields (e.g. jacoco fields)
+                        // otherwise IllegalAccessException (can be bypassed with Unsafe though)
+                        // We may also miss coverage data.
+                        continue;
+                    }
+                    if (declaredField.getType() == field.getType()) { // don't copy this
+                        field.setAccessible(true);
+                        declaredField.setAccessible(true);
+                        declaredField.set(reloaded, field.get(task));
+                    }
+                }
+
+                return reloaded;
+            } catch (ClassNotFoundException e) {
+                throw new IllegalStateException(e);
+            } catch (IllegalAccessException e) {
+                throw new IllegalStateException(e);
+            } catch (NoSuchFieldException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+
+    public static class IsolatedURLClassLoaderBuilder extends ClassLoaders {
+        private final ArrayList<String> excludedPrefixes = new ArrayList<String>();
+        private final ArrayList<String> privateCopyPrefixes = new ArrayList<String>();
+        private final ArrayList<URL> codeSourceUrls = new ArrayList<URL>();
+
+        public IsolatedURLClassLoaderBuilder withPrivateCopyOf(String... privatePrefixes) {
+            privateCopyPrefixes.addAll(asList(privatePrefixes));
+            return this;
+        }
+
+        public IsolatedURLClassLoaderBuilder withCodeSourceUrls(String... urls) {
+            codeSourceUrls.addAll(pathsToURLs(urls));
+            return this;
+        }
+
+        public IsolatedURLClassLoaderBuilder withCodeSourceUrlOf(Class<?>... classes) {
+            for (Class<?> clazz : classes) {
+                codeSourceUrls.add(obtainCurrentClassPathOf(clazz.getName()));
+            }
+            return this;
+        }
+
+        public IsolatedURLClassLoaderBuilder withCurrentCodeSourceUrls() {
+            codeSourceUrls.add(obtainCurrentClassPathOf(ClassLoaders.class.getName()));
+            return this;
+        }
+
+        public IsolatedURLClassLoaderBuilder without(String... privatePrefixes) {
+            excludedPrefixes.addAll(asList(privatePrefixes));
+            return this;
+        }
+
+        public ClassLoader build() {
+            return new LocalIsolatedURLClassLoader(
+                    jdkClassLoader(),
+                    codeSourceUrls.toArray(new URL[codeSourceUrls.size()]),
+                    privateCopyPrefixes,
+                    excludedPrefixes
+            );
+        }
+    }
+
+    static class LocalIsolatedURLClassLoader extends URLClassLoader {
+        private final ArrayList<String> privateCopyPrefixes;
+        private final ArrayList<String> excludedPrefixes;
+
+        LocalIsolatedURLClassLoader(ClassLoader classLoader,
+                                    URL[] urls,
+                                    ArrayList<String> privateCopyPrefixes,
+                                    ArrayList<String> excludedPrefixes) {
+            super(urls, classLoader);
+            this.privateCopyPrefixes = privateCopyPrefixes;
+            this.excludedPrefixes = excludedPrefixes;
+        }
+
+        @Override
+        public Class<?> findClass(String name) throws ClassNotFoundException {
+            if (!classShouldBePrivate(name) || classShouldBeExcluded(name)) {
+                throw new ClassNotFoundException(format("Can only load classes with prefixes : %s, but not : %s",
+                                                        privateCopyPrefixes,
+                                                        excludedPrefixes));
+            }
+            try {
+                return super.findClass(name);
+            } catch (ClassNotFoundException cnfe) {
+                throw new ClassNotFoundException(format("%s%n%s%n",
+                                                        cnfe.getMessage(),
+                                                        "    Did you forgot to add the code source url 'withCodeSourceUrlOf' / 'withCurrentCodeSourceUrls' ?"),
+                                                 cnfe);
+            }
+        }
+
+        private boolean classShouldBePrivate(String name) {
+            for (String prefix : privateCopyPrefixes) {
+                if (name.startsWith(prefix)) return true;
+            }
+            return false;
+        }
+
+        private boolean classShouldBeExcluded(String name) {
+            for (String prefix : excludedPrefixes) {
+                if (name.startsWith(prefix)) return true;
+            }
+            return false;
+        }
+    }
+
+    public static class ExcludingURLClassLoaderBuilder extends ClassLoaders {
+        private final ArrayList<String> excludedPrefixes = new ArrayList<String>();
+        private final ArrayList<URL> codeSourceUrls = new ArrayList<URL>();
+
+        public ExcludingURLClassLoaderBuilder without(String... privatePrefixes) {
+            excludedPrefixes.addAll(asList(privatePrefixes));
+            return this;
+        }
+
+        public ExcludingURLClassLoaderBuilder withCodeSourceUrls(String... urls) {
+            codeSourceUrls.addAll(pathsToURLs(urls));
+            return this;
+        }
+
+        public ExcludingURLClassLoaderBuilder withCodeSourceUrlOf(Class<?>... classes) {
+            for (Class<?> clazz : classes) {
+                codeSourceUrls.add(obtainCurrentClassPathOf(clazz.getName()));
+            }
+            return this;
+        }
+
+        public ExcludingURLClassLoaderBuilder withCurrentCodeSourceUrls() {
+            codeSourceUrls.add(obtainCurrentClassPathOf(ClassLoaders.class.getName()));
+            return this;
+        }
+
+        public ClassLoader build() {
+            return new LocalExcludingURLClassLoader(
+                    jdkClassLoader(),
+                    codeSourceUrls.toArray(new URL[codeSourceUrls.size()]),
+                    excludedPrefixes
+            );
+        }
+    }
+
+    static class LocalExcludingURLClassLoader extends URLClassLoader {
+        private final ArrayList<String> excludedPrefixes;
+
+        LocalExcludingURLClassLoader(ClassLoader classLoader,
+                                     URL[] urls,
+                                     ArrayList<String> excludedPrefixes) {
+            super(urls, classLoader);
+            this.excludedPrefixes = excludedPrefixes;
+        }
+
+        @Override
+        public Class<?> findClass(String name) throws ClassNotFoundException {
+            if (classShouldBeExcluded(name))
+                throw new ClassNotFoundException("classes with prefix : " + excludedPrefixes + " are excluded");
+            return super.findClass(name);
+        }
+
+        private boolean classShouldBeExcluded(String name) {
+            for (String prefix : excludedPrefixes) {
+                if (name.startsWith(prefix)) return true;
+            }
+            return false;
+        }
+    }
+
+    public static class InMemoryClassLoaderBuilder extends ClassLoaders {
+        private Map<String, byte[]> inMemoryClassObjects = new HashMap<String, byte[]>();
+
+        public InMemoryClassLoaderBuilder withParent(ClassLoader parent) {
+            this.parent = parent;
+            return this;
+        }
+
+        public InMemoryClassLoaderBuilder withClassDefinition(String name, byte[] classDefinition) {
+            inMemoryClassObjects.put(name, classDefinition);
+            return this;
+        }
+
+        public ClassLoader build() {
+            return new InMemoryClassLoader(parent, inMemoryClassObjects);
+        }
+    }
+
+    static class InMemoryClassLoader extends ClassLoader {
+        public static final String SCHEME = "mem";
+        private Map<String, byte[]> inMemoryClassObjects = new HashMap<String, byte[]>();
+
+        public InMemoryClassLoader(ClassLoader parent, Map<String, byte[]> inMemoryClassObjects) {
+            super(parent);
+            this.inMemoryClassObjects = inMemoryClassObjects;
+        }
+
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            byte[] classDefinition = inMemoryClassObjects.get(name);
+            if (classDefinition != null) {
+                return defineClass(name, classDefinition, 0, classDefinition.length);
+            }
+            throw new ClassNotFoundException(name);
+        }
+
+        @Override
+        public Enumeration<URL> getResources(String ignored) throws IOException {
+            return inMemoryOnly();
+        }
+
+        private Enumeration<URL> inMemoryOnly() {
+            final Set<String> names = inMemoryClassObjects.keySet();
+            return new Enumeration<URL>() {
+                private final MemHandler memHandler = new MemHandler(InMemoryClassLoader.this);
+                private final Iterator<String> it = names.iterator();
+
+                public boolean hasMoreElements() {
+                    return it.hasNext();
+                }
+
+                public URL nextElement() {
+                    try {
+                        return new URL(null, SCHEME + ":" + it.next(), memHandler);
+                    } catch (MalformedURLException rethrown) {
+                        throw new IllegalStateException(rethrown);
+                    }
+                }
+            };
+        }
+    }
+
+    public static class MemHandler extends URLStreamHandler {
+        private InMemoryClassLoader inMemoryClassLoader;
+
+        public MemHandler(InMemoryClassLoader inMemoryClassLoader) {
+            this.inMemoryClassLoader = inMemoryClassLoader;
+        }
+
+        @Override
+        protected URLConnection openConnection(URL url) throws IOException {
+            return new MemURLConnection(url, inMemoryClassLoader);
+        }
+
+        private static class MemURLConnection extends URLConnection {
+            private final InMemoryClassLoader inMemoryClassLoader;
+            private String qualifiedName;
+
+            public MemURLConnection(URL url, InMemoryClassLoader inMemoryClassLoader) {
+                super(url);
+                this.inMemoryClassLoader = inMemoryClassLoader;
+                qualifiedName = url.getPath();
+            }
+
+            @Override
+            public void connect() throws IOException {
+            }
+
+            @Override
+            public InputStream getInputStream() throws IOException {
+                return new ByteArrayInputStream(inMemoryClassLoader.inMemoryClassObjects.get(qualifiedName));
+            }
+        }
+    }
+
+    URL obtainCurrentClassPathOf(String className) {
+        String path = className.replace('.', '/') + ".class";
+        String url = ClassLoaders.class.getClassLoader().getResource(path).toExternalForm();
+
+        try {
+            return new URL(url.substring(0, url.length() - path.length()));
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("Classloader couldn't obtain a proper classpath URL", e);
+        }
+    }
+
+    List<URL> pathsToURLs(String... codeSourceUrls) {
+        return pathsToURLs(Arrays.asList(codeSourceUrls));
+    }
+
+    private List<URL> pathsToURLs(List<String> codeSourceUrls) {
+        ArrayList<URL> urls = new ArrayList<URL>(codeSourceUrls.size());
+        for (String codeSourceUrl : codeSourceUrls) {
+            URL url = pathToUrl(codeSourceUrl);
+            urls.add(url);
+        }
+        return urls;
+    }
+
+    private URL pathToUrl(String path) {
+        try {
+            return new File(path).getAbsoluteFile().toURI().toURL();
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException("Path is malformed", e);
+        }
+    }
+
+    public static class ReachableClassesFinder {
+        private ClassLoader classLoader;
+        private Set<String> qualifiedNameSubstring = new HashSet<String>();
+
+        ReachableClassesFinder(ClassLoader classLoader) {
+            this.classLoader = classLoader;
+        }
+
+        public ReachableClassesFinder omit(String... qualifiedNameSubstring) {
+            this.qualifiedNameSubstring.addAll(Arrays.asList(qualifiedNameSubstring));
+            return this;
+        }
+
+        public Set<String> listOwnedClasses() throws IOException, URISyntaxException {
+            Enumeration<URL> roots = classLoader.getResources("");
+
+            Set<String> classes = new HashSet<String>();
+            while (roots.hasMoreElements()) {
+                URI uri = roots.nextElement().toURI();
+
+                if (uri.getScheme().equalsIgnoreCase("file")) {
+                    addFromFileBasedClassLoader(classes, uri);
+                } else if (uri.getScheme().equalsIgnoreCase(InMemoryClassLoader.SCHEME)) {
+                    addFromInMemoryBasedClassLoader(classes, uri);
+                } else {
+                    throw new IllegalArgumentException(format("Given ClassLoader '%s' don't have reachable by File or vi ClassLoaders.inMemory", classLoader));
+                }
+            }
+            return classes;
+        }
+
+        private void addFromFileBasedClassLoader(Set<String> classes, URI uri) {
+            File root = new File(uri);
+            classes.addAll(findClassQualifiedNames(root, root, qualifiedNameSubstring));
+        }
+
+        private void addFromInMemoryBasedClassLoader(Set<String> classes, URI uri) {
+            String qualifiedName = uri.getSchemeSpecificPart();
+            if (excludes(qualifiedName, qualifiedNameSubstring)) {
+                classes.add(qualifiedName);
+            }
+        }
+
+
+        private Set<String> findClassQualifiedNames(File root, File file, Set<String> packageFilters) {
+            if (file.isDirectory()) {
+                File[] files = file.listFiles();
+                Set<String> classes = new HashSet<String>();
+                for (File children : files) {
+                    classes.addAll(findClassQualifiedNames(root, children, packageFilters));
+                }
+                return classes;
+            } else {
+                if (file.getName().endsWith(".class")) {
+                    String qualifiedName = classNameFor(root, file);
+                    if (excludes(qualifiedName, packageFilters)) {
+                        return Collections.singleton(qualifiedName);
+                    }
+                }
+            }
+            return Collections.emptySet();
+        }
+
+        private boolean excludes(String qualifiedName, Set<String> packageFilters) {
+            for (String filter : packageFilters) {
+                if (qualifiedName.contains(filter)) return false;
+            }
+            return true;
+        }
+
+        private String classNameFor(File root, File file) {
+            String temp = file.getAbsolutePath().substring(root.getAbsolutePath().length() + 1).
+                    replace(File.separatorChar, '.');
+            return temp.subSequence(0, temp.indexOf(".class")).toString();
+        }
+
+    }
+}
diff --git a/src/test/java/org/mockitoutil/ClassLoadersTest.java b/src/test/java/org/mockitoutil/ClassLoadersTest.java
new file mode 100644
index 0000000..545dac4
--- /dev/null
+++ b/src/test/java/org/mockitoutil/ClassLoadersTest.java
@@ -0,0 +1,340 @@
+package org.mockitoutil;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockitoutil.ClassLoaders.currentClassLoader;
+import static org.mockitoutil.ClassLoaders.excludingClassLoader;
+import static org.mockitoutil.ClassLoaders.isolatedClassLoader;
+import static org.mockitoutil.ClassLoaders.jdkClassLoader;
+
+public class ClassLoadersTest {
+
+    public static final String CLASS_NAME_DEPENDING_ON_INTERFACE = "org.mockitoutil.ClassLoadersTest$ClassUsingInterface1";
+    public static final String INTERFACE_NAME = "org.mockitoutil.ClassLoadersTest$Interface1";
+
+    @Test(expected = ClassNotFoundException.class)
+    public void isolated_class_loader_cannot_load_classes_when_no_given_prefix() throws Exception {
+        // given
+        ClassLoader cl = isolatedClassLoader().build();
+
+        // when
+        cl.loadClass("org.mockito.Mockito");
+
+        // then raises CNFE
+    }
+
+    @Test
+    public void isolated_class_loader_cannot_load_classes_if_no_code_source_path() throws Exception {
+        // given
+        ClassLoader cl = isolatedClassLoader()
+                .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
+                .build();
+
+        // when
+        try {
+            cl.loadClass(CLASS_NAME_DEPENDING_ON_INTERFACE);
+            fail();
+        } catch (ClassNotFoundException e) {
+            // then
+            assertThat(e).hasMessageContaining(CLASS_NAME_DEPENDING_ON_INTERFACE);
+        }
+    }
+
+    @Test
+    public void isolated_class_loader_cannot_load_classes_if_dependent_classes_do_not_match_the_prefixes() throws Exception {
+        // given
+        ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
+                .build();
+
+        // when
+        try {
+            cl.loadClass(CLASS_NAME_DEPENDING_ON_INTERFACE);
+            fail();
+        } catch (NoClassDefFoundError e) {
+            // then
+            assertThat(e).hasMessageContaining("org/mockitoutil/ClassLoadersTest$Interface1");
+        }
+    }
+
+    @Test
+    public void isolated_class_loader_can_load_classes_when_dependent_classes_are_matching_the_prefixes() throws Exception {
+        // given
+        ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
+                .withPrivateCopyOf(INTERFACE_NAME)
+                .build();
+
+        // when
+        Class<?> aClass = cl.loadClass(CLASS_NAME_DEPENDING_ON_INTERFACE);
+
+        // then
+        assertThat(aClass).isNotNull();
+        assertThat(aClass.getClassLoader()).isEqualTo(cl);
+        assertThat(aClass.getInterfaces()[0].getClassLoader()).isEqualTo(cl);
+    }
+
+    @Test
+    public void isolated_class_loader_can_load_classes_isolated_classes_in_isolation() throws Exception {
+        // given
+        ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
+                .build();
+
+        // when
+        Class<?> aClass = cl.loadClass(AClass.class.getName());
+
+        // then
+        assertThat(aClass).isNotNull();
+        assertThat(aClass).isNotSameAs(AClass.class);
+        assertThat(aClass.getClassLoader()).isEqualTo(cl);
+    }
+
+    @Test
+    public void isolated_class_loader_cannot_load_classes_if_prefix_excluded() throws Exception {
+        // given
+        ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
+                .without(AClass.class.getName())
+                .build();
+
+        // when
+        try {
+            cl.loadClass(AClass.class.getName());
+            fail();
+        } catch (ClassNotFoundException e) {
+            // then
+            assertThat(e).hasMessageContaining("org.mockitoutil")
+                         .hasMessageContaining(AClass.class.getName());
+        }
+    }
+
+    @Test
+    public void isolated_class_loader_has_no_parent() throws Exception {
+        ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
+                .withPrivateCopyOf(INTERFACE_NAME)
+                .build();
+
+        assertThat(cl.getParent()).isNull();
+    }
+
+    @Test(expected = ClassNotFoundException.class)
+    public void excluding_class_loader_cannot_load_classes_when_no_correct_source_url_set() throws Exception {
+        // given
+        ClassLoader cl = excludingClassLoader()
+                .withCodeSourceUrlOf(this.getClass())
+                .build();
+
+        // when
+        cl.loadClass("org.mockito.Mockito");
+
+        // then class CNFE
+    }
+
+    @Test
+    public void excluding_class_loader_can_load_classes_when_correct_source_url_set() throws Exception {
+        // given
+        ClassLoader cl = excludingClassLoader()
+                .withCodeSourceUrlOf(Mockito.class)
+                .build();
+
+        // when
+        cl.loadClass("org.mockito.Mockito");
+
+        // then class successfully loaded
+    }
+
+    @Test
+    public void excluding_class_loader_cannot_load_class_when_excluded_prefix_match_class_to_load() throws Exception {
+        // given
+        ClassLoader cl = excludingClassLoader()
+                .withCodeSourceUrlOf(Mockito.class)
+                .without("org.mockito.BDDMockito")
+                .build();
+
+        cl.loadClass("org.mockito.Mockito");
+
+        // when
+        try {
+            cl.loadClass("org.mockito.BDDMockito");
+            fail("should have raise a ClassNotFoundException");
+        } catch (ClassNotFoundException e) {
+            assertThat(e.getMessage()).contains("org.mockito.BDDMockito");
+        }
+
+        // then class successfully loaded
+    }
+
+    @Test
+    public void can_not_load_a_class_not_previously_registered_in_builder() throws Exception {
+        // given
+        ClassLoader cl = ClassLoaders
+                .inMemoryClassLoader()
+                .withClassDefinition("yop.Dude", SimpleClassGenerator.makeMarkerInterface("yop.Dude"))
+                .build();
+
+        // when
+        try {
+            cl.loadClass("not.Defined");
+            fail();
+        } catch (ClassNotFoundException e) {
+            // then
+            assertThat(e.getMessage()).contains("not.Defined");
+        }
+    }
+
+    @Test
+    public void can_load_a_class_in_memory_from_bytes() throws Exception {
+        // given
+        ClassLoader cl = ClassLoaders
+                .inMemoryClassLoader()
+                .withClassDefinition("yop.Dude", SimpleClassGenerator.makeMarkerInterface("yop.Dude"))
+                .build();
+
+        // when
+        Class<?> aClass = cl.loadClass("yop.Dude");
+
+        // then
+        assertThat(aClass).isNotNull();
+        assertThat(aClass.getClassLoader()).isEqualTo(cl);
+        assertThat(aClass.getName()).isEqualTo("yop.Dude");
+    }
+
+    @Test
+    public void cannot_load_a_class_file_not_in_parent() throws Exception {
+        // given
+        ClassLoader cl = ClassLoaders
+                .inMemoryClassLoader()
+                .withParent(jdkClassLoader())
+                .build();
+
+        cl.loadClass("java.lang.String");
+
+        try {
+            // when
+            cl.loadClass("org.mockito.Mockito");
+            fail("should have not found Mockito class");
+        } catch (ClassNotFoundException e) {
+            // then
+            assertThat(e.getMessage()).contains("org.mockito.Mockito");
+        }
+    }
+
+    @Test
+    public void can_list_all_classes_reachable_in_a_classloader() throws Exception {
+        ClassLoader classLoader = ClassLoaders.inMemoryClassLoader()
+                                              .withParent(jdkClassLoader())
+                                              .withClassDefinition("a.A", SimpleClassGenerator.makeMarkerInterface("a.A"))
+                                              .withClassDefinition("a.b.B", SimpleClassGenerator.makeMarkerInterface("a.b.B"))
+                                              .withClassDefinition("c.C", SimpleClassGenerator.makeMarkerInterface("c.C"))
+//                .withCodeSourceUrlOf(ClassLoaders.class)
+                                              .build();
+
+        assertThat(ClassLoaders.in(classLoader).listOwnedClasses()).containsOnly("a.A", "a.b.B", "c.C");
+        assertThat(ClassLoaders.in(classLoader).omit("b", "c").listOwnedClasses()).containsOnly("a.A");
+    }
+
+    @Test
+    public void return_bootstrap_classloader() throws Exception {
+        assertThat(jdkClassLoader()).isNotEqualTo(Mockito.class.getClassLoader());
+        assertThat(jdkClassLoader()).isNotEqualTo(ClassLoaders.class.getClassLoader());
+        assertThat(jdkClassLoader()).isEqualTo(Number.class.getClassLoader());
+        assertThat(jdkClassLoader()).isEqualTo(null);
+    }
+
+    @Test
+    public void return_current_classloader() throws Exception {
+        assertThat(currentClassLoader()).isEqualTo(this.getClass().getClassLoader());
+    }
+
+    @Test
+    public void can_run_in_given_classloader() throws Exception {
+        // given
+        final ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withCodeSourceUrlOf(Assertions.class)
+                .withPrivateCopyOf("org.assertj.core")
+                .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
+                .without(AClass.class.getName())
+                .build();
+
+        final AtomicBoolean executed = new AtomicBoolean(false);
+
+        // when
+        ClassLoaders.using(cl).execute(new Runnable() {
+            @Override
+            public void run() {
+                assertThat(this.getClass().getClassLoader()).describedAs("runnable is reloaded in given classloader").isEqualTo(cl);
+                assertThat(Thread.currentThread().getContextClassLoader()).describedAs("Thread context classloader is using given classloader").isEqualTo(cl);
+
+                try {
+                    assertThat(Thread.currentThread()
+                                     .getContextClassLoader()
+                                     .loadClass("java.lang.String"))
+                            .describedAs("can load JDK type")
+                            .isNotNull();
+                    assertThat(Thread.currentThread()
+                                     .getContextClassLoader()
+                                     .loadClass("org.mockitoutil.ClassLoadersTest$ClassUsingInterface1"))
+                            .describedAs("can load classloader types")
+                            .isNotNull();
+                } catch (ClassNotFoundException cnfe) {
+                    Assertions.fail("should not have raised a CNFE", cnfe);
+                }
+                executed.set(true);
+            }
+        });
+
+        // then
+        assertThat(executed.get()).isEqualTo(true);
+    }
+
+
+    @Test
+    public void cannot_load_runnable_in_given_classloader_if_some_type_cant_be_loaded() throws Exception {
+        // given
+        final ClassLoader cl = isolatedClassLoader()
+                .withCurrentCodeSourceUrls()
+                .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
+                .without(AClass.class.getName())
+                .build();
+
+        // when
+        try {
+            ClassLoaders.using(cl).execute(new Runnable() {
+                @Override
+                public void run() {
+                    AClass cant_be_found = new AClass();
+                }
+            });
+            Assertions.fail("should have raised a ClassNotFoundException");
+        } catch (IllegalStateException ise) {
+            // then
+            assertThat(ise).hasCauseInstanceOf(NoClassDefFoundError.class)
+                           .hasMessageContaining("AClass");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    static class AClass {
+    }
+
+    @SuppressWarnings("unused")
+    static class ClassUsingInterface1 implements Interface1 {
+    }
+
+    @SuppressWarnings("unused")
+    interface Interface1 {
+    }
+}
diff --git a/src/test/java/org/mockitoutil/ConcurrentTesting.java b/src/test/java/org/mockitoutil/ConcurrentTesting.java
new file mode 100644
index 0000000..da7d1bc
--- /dev/null
+++ b/src/test/java/org/mockitoutil/ConcurrentTesting.java
@@ -0,0 +1,36 @@
+package org.mockitoutil;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Utility methods for concurrent testing
+ */
+public class ConcurrentTesting {
+
+    /**
+     * Executes given runnable in thread and waits for completion
+     */
+    public static void inThread(Runnable r) throws InterruptedException {
+        Thread t = new Thread(r);
+        t.start();
+        t.join();
+    }
+
+    /**
+     * Starts all supplied runnables and then waits for all of them to complete.
+     * Runnables are executed concurrently.
+     */
+    public static void concurrently(Runnable ... runnables) throws InterruptedException {
+        List<Thread> threads = new LinkedList<Thread>();
+        for (Runnable r : runnables) {
+            Thread t = new Thread(r);
+            t.start();
+            threads.add(t);
+        }
+
+        for (Thread t : threads) {
+            t.join();
+        }
+    }
+}
diff --git a/src/test/java/org/mockitoutil/Conditions.java b/src/test/java/org/mockitoutil/Conditions.java
new file mode 100644
index 0000000..202737f
--- /dev/null
+++ b/src/test/java/org/mockitoutil/Conditions.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitoutil;
+
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.Condition;
+import org.assertj.core.description.Description;
+import org.assertj.core.description.TextDescription;
+import org.hamcrest.CoreMatchers;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+@SuppressWarnings("unchecked")
+public class Conditions {
+
+    public static Condition<Throwable> onlyThoseClassesInStackTrace(final String... classes) {
+        return new Condition<Throwable>() {
+            @Override
+            public boolean matches(Throwable traceElements) {
+                StackTraceElement[] trace = traceElements.getStackTrace();
+
+                Assertions.assertThat(trace.length)
+                          .describedAs("Number of classes does not match.\nExpected: %s\nGot: %s",
+                                       Arrays.toString(classes),
+                                       Arrays.toString(traceElements.getStackTrace()))
+                          .isEqualTo(classes.length);
+
+                for (int i = 0; i < trace.length; i++) {
+                    Assertions.assertThat(trace[i].getClassName()).isEqualTo(classes[i]);
+                }
+
+                return true;
+            }
+        };
+    }
+
+    public static Condition<StackTraceElement[]> onlyThoseClasses(final String... classes) {
+        return new Condition<StackTraceElement[]>() {
+
+            @Override
+            public boolean matches(StackTraceElement[] traceElements) {
+                Assertions.assertThat(traceElements.length)
+                          .describedAs("Number of classes does not match.\nExpected: %s\nGot: %s",
+                                       Arrays.toString(classes),
+                                       Arrays.toString(traceElements))
+                          .isEqualTo(classes.length);
+
+                for (int i = 0; i < traceElements.length; i++) {
+                    Assertions.assertThat(traceElements[i].getClassName()).isEqualTo(classes[i]);
+                }
+
+                return true;
+            }
+        };
+    }
+
+    public static Condition<Throwable> firstMethodInStackTrace(final String method) {
+        return methodInStackTraceAt(0, method);
+    }
+
+    public static Condition<Throwable> methodInStackTraceAt(final int stackTraceIndex, final String method) {
+        return new Condition<Throwable>() {
+            private String actualMethodAtIndex;
+
+            @Override
+            public boolean matches(Throwable throwable) {
+                actualMethodAtIndex = throwable.getStackTrace()[stackTraceIndex].getMethodName();
+
+                return actualMethodAtIndex.equals(method);
+            }
+
+            @Override
+            public Description description() {
+                return new TextDescription("Method at index: %d\nexpected to be: %s\nbut is: %s", stackTraceIndex, method, actualMethodAtIndex);
+            }
+        };
+    }
+
+    public static Condition<Object> bridgeMethod(final String methodName) {
+        return new Condition<Object>() {
+
+            public boolean matches(Object o) {
+                Class<?> clazz = null;
+                if (o instanceof Class) {
+                    clazz = (Class<?>) o;
+                } else {
+                    clazz = o.getClass();
+                }
+
+                for (Method m : clazz.getMethods()) {
+                    if (m.isBridge() && m.getName().equals(methodName)) {
+                        return true;
+                    }
+                }
+
+                Assertions.fail("Bridge method [" + methodName + "]\nnot found in:\n" + o);
+                return false;
+            }
+        };
+    }
+
+    public static org.hamcrest.Matcher<Object> clazz(Class<?> type) {
+        return CoreMatchers.instanceOf(type);
+    }
+
+    public static Condition<Throwable> methodsInStackTrace(final String... methods) {
+        return new Condition<Throwable>() {
+            public boolean matches(Throwable value) {
+                StackTraceElement[] trace = value.getStackTrace();
+                for (int i = 0; i < methods.length; i++) {
+                    Assertions.assertThat(trace[i].getMethodName()).describedAs("Expected methods[%d] to be in the stack trace.", i).isEqualTo(methods[i]);
+                }
+                return true;
+            }
+        };
+    }
+
+
+}
diff --git a/src/test/java/org/mockitoutil/JUnitResultAssert.java b/src/test/java/org/mockitoutil/JUnitResultAssert.java
new file mode 100644
index 0000000..0300a3f
--- /dev/null
+++ b/src/test/java/org/mockitoutil/JUnitResultAssert.java
@@ -0,0 +1,135 @@
+package org.mockitoutil;
+
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.internal.util.collections.Iterables.firstOf;
+import static org.mockitoutil.TestBase.filterLineNo;
+
+/**
+ * Assertion utility for cleaner & easier to debug tests that inspect on JUnit's Result object
+ */
+public class JUnitResultAssert {
+    private Result result;
+
+    private JUnitResultAssert(Result result) {
+        this.result = result;
+    }
+
+    public void isSuccessful() {
+        if (result.wasSuccessful()) {
+            return;
+        }
+
+        throw new AssertionError(formatFailures(result.getFailures()));
+    }
+
+    /**
+     * @param expectedFailureCount - expected number of failures
+     * @param expectedException - the exception of each failure
+     */
+    public JUnitResultAssert fails(int expectedFailureCount, Class expectedException) {
+        fails(expectedFailureCount);
+        for (Failure f : result.getFailures()) {
+            if (!expectedException.isInstance(f.getException())) {
+                throw new AssertionError("Incorrect failure type, expected: " + expectedException + ", actual: " + f.getException().getClass().getSimpleName() + "\n" +
+                        formatFailures(result.getFailures()));
+            }
+        }
+        return this;
+    }
+
+    /**
+     * @param expectedFailureCount - exact number of expected failures
+     */
+    public JUnitResultAssert fails(int expectedFailureCount) {
+        if (result.getFailures().size() != expectedFailureCount) {
+            throw new AssertionError("Wrong number of failures, expected: " + expectedFailureCount + ", actual: " + result.getFailures().size() + "\n" +
+                    formatFailures(result.getFailures()));
+        }
+        return this;
+    }
+
+    /**
+     * @param expectedExceptions - failures must match the supplied sequence in order,
+     *                           if supplied input is empty, this method is a no-op
+     */
+    public JUnitResultAssert failsExactly(Class ... expectedExceptions) {
+        fails(expectedExceptions.length);
+        int i = 0;
+        for (Failure f : result.getFailures()) {
+            if (!expectedExceptions[i].isInstance(f.getException())) {
+                throw new AssertionError("Actual failure #" + (i+1)
+                        + " should be of type: " + expectedExceptions[i].getSimpleName()
+                        + " but is of type: " + f.getException().getClass().getSimpleName()
+                        + "\n" + formatFailures(result.getFailures()));
+            }
+            i++;
+        }
+        return this;
+    }
+
+    /**
+     * Expects single failure with specific exception and exception message.
+     * Automatically filters line numbers from exception messages.
+     */
+    public JUnitResultAssert fails(Class expectedException, String exceptionMessage) {
+        fails(1, expectedException);
+        Failure f = firstOf(result.getFailures());
+        assertEquals(filterLineNo(exceptionMessage), filterLineNo(f.getException().getMessage()));
+        return this;
+    }
+
+    /**
+     * Expects failure of given test method with given exception
+     */
+    public JUnitResultAssert fails(String methodName, Class expectedException) {
+        for (Failure f : result.getFailures()) {
+            if (methodName.equals(f.getDescription().getMethodName()) && expectedException.isInstance(f.getException())) {
+                return this;
+            }
+        }
+        throw new AssertionError("Method '" + methodName + "' did not fail with: " + expectedException.getSimpleName()
+                + "\n" + formatFailures(result.getFailures()));
+    }
+
+    /**
+     * Expects given amount of failures, with given exception triggered by given test method
+     */
+    public JUnitResultAssert fails(int expectedFailureCount, String methodName, Class expectedException) {
+        return fails(expectedFailureCount, expectedException)
+                .fails(methodName, expectedException);
+    }
+
+    public JUnitResultAssert succeeds(int successCount) {
+        int i = result.getRunCount() - result.getFailureCount();
+        if (i != successCount) {
+            throw new AssertionError("Expected " + successCount + " passes but " + i + "/" + result.getRunCount() + " passed." +
+                    "\n" + formatFailures(result.getFailures()));
+        }
+        return this;
+    }
+
+    private static String formatFailures(List<Failure> failures) {
+        if (failures.isEmpty()) {
+            return "<no failures>";
+        }
+        StringBuilder sb = new StringBuilder("There were " + failures.size() + " test failures:\n");
+        int count = 0;
+        for (Failure f : failures) {
+            sb.append("  <-----> ").append(++count).append(". ").append(f.getTrace()).append("\n");
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Clean assertions for JUnit's result object
+     */
+    public static JUnitResultAssert assertThat(Result result) {
+        return new JUnitResultAssert(result);
+    }
+}
diff --git a/src/test/java/org/mockitoutil/RetryRule.java b/src/test/java/org/mockitoutil/RetryRule.java
new file mode 100644
index 0000000..386ce78
--- /dev/null
+++ b/src/test/java/org/mockitoutil/RetryRule.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitoutil;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import static java.lang.String.format;
+
+public class RetryRule implements TestRule {
+    private final TestRule innerRule;
+
+    public static RetryRule attempts(final int attempts) {
+        return new RetryRule(new NumberedAttempts(attempts));
+    }
+
+    private RetryRule(TestRule innerRule) {
+        this.innerRule = innerRule;
+    }
+
+    public Statement apply(final Statement base, final Description description) {
+        return innerRule.apply(base, description);
+    }
+
+    private static class NumberedAttempts implements TestRule {
+        private final int attempts;
+
+        NumberedAttempts(int attempts) {
+            assert attempts > 1;
+            this.attempts = attempts;
+        }
+
+        @Override
+        public Statement apply(final Statement base, final Description description) {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    for (int remainingAttempts = attempts; remainingAttempts > 0 ; remainingAttempts--) {
+                        try {
+                            base.evaluate();
+                        } catch (Throwable throwable) {
+                            if (remainingAttempts < 0) {
+                                throw new AssertionError(format("Tried this test + %d times and failed", attempts))
+                                        .initCause(throwable);
+                            }
+                        }
+                    }
+                }
+            };
+        }
+    }
+}
diff --git a/src/test/java/org/mockitoutil/SafeJUnitRule.java b/src/test/java/org/mockitoutil/SafeJUnitRule.java
new file mode 100644
index 0000000..eb06d2e
--- /dev/null
+++ b/src/test/java/org/mockitoutil/SafeJUnitRule.java
@@ -0,0 +1,102 @@
+package org.mockitoutil;
+
+import org.assertj.core.api.AbstractThrowableAssert;
+import org.assertj.core.api.Assertions;
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+/**
+ * Junit rule for testing exception handling other JUnit rules, like Mockito JUnit rules.
+ * Makes it easy to assert on expected exceptions triggered by the rule under test.
+ */
+public class SafeJUnitRule implements MethodRule {
+
+    private final MethodRule testedRule;
+    private FailureAssert failureAssert = null;
+    private Runnable successAssert = new Runnable() { public void run() { } };
+
+    /**
+     * Wraps rule under test with exception handling so that it is easy to assert on exceptions fired from the tested rule.
+     */
+    public SafeJUnitRule(MethodRule testedRule) {
+        this.testedRule = testedRule;
+    }
+
+    public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+        return new Statement() {
+            public void evaluate() throws Throwable {
+                try {
+                    testedRule.apply(base, method, target).evaluate();
+                    successAssert.run();
+                } catch (Throwable t) {
+                    if (failureAssert == null) {
+                        throw t;
+                    }
+                    failureAssert.doAssert(t);
+                    return;
+                }
+                if (failureAssert != null) {
+                    //looks like the user expects a throwable but it was not thrown!
+                    throw new ExpectedThrowableNotReported("Expected the tested rule to throw an exception but it did not.");
+                }
+            }
+        };
+    }
+
+    /**
+     * Expects that _after_ the test, the rule will fire specific exception with specific exception message
+     */
+    public void expectFailure(final Class<? extends Throwable> expected, final String expectedMessage) {
+        this.expectFailure(new FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertThrowable(t, expected).hasMessage(expectedMessage);
+            }
+        });
+    }
+
+    /**
+     * Expects that _after_ the test, the rule will fire specific exception with specific exception message
+     */
+    public void expectFailure(final Class<? extends Throwable> expected) {
+        this.expectFailure(new FailureAssert() {
+            public void doAssert(Throwable t) {
+                assertThrowable(t, expected);
+            }
+        });
+    }
+
+    private static AbstractThrowableAssert assertThrowable(Throwable throwable, Class<? extends Throwable> expected) {
+        return Assertions.assertThat(throwable).isInstanceOf(expected);
+    }
+
+    /**
+     * Expects that _after_ the test, the rule will fire an exception
+     */
+    public void expectFailure(FailureAssert failureAssert) {
+        this.failureAssert = failureAssert;
+    }
+
+    /**
+     * Expects that _after_ the test, given assert will run
+     */
+    public void expectSuccess(Runnable successAssert) {
+        this.successAssert = successAssert;
+    }
+
+    /**
+     * Offers a way to assert the throwable triggered by the tested rule
+     */
+    public interface FailureAssert {
+        void doAssert(Throwable t);
+    }
+
+    /**
+     * Thrown when user expects the tested rule to throw an exception but no exception was thrown
+     */
+    class ExpectedThrowableNotReported extends Throwable {
+        public ExpectedThrowableNotReported(String message) {
+            super(message);
+        }
+    }
+}
diff --git a/src/test/java/org/mockitoutil/SafeJUnitRuleTest.java b/src/test/java/org/mockitoutil/SafeJUnitRuleTest.java
new file mode 100644
index 0000000..aa6ab9e
--- /dev/null
+++ b/src/test/java/org/mockitoutil/SafeJUnitRuleTest.java
@@ -0,0 +1,136 @@
+package org.mockitoutil;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+public class SafeJUnitRuleTest {
+
+    MethodRuleStub delegate = new MethodRuleStub();
+    SafeJUnitRule rule = new SafeJUnitRule(delegate);
+
+    @Test public void happy_path_no_exception() throws Throwable {
+        //when
+        rule.apply(new Statement() {
+            public void evaluate() throws Throwable {
+                //all good
+            }
+        }, mock(FrameworkMethod.class), this).evaluate();
+
+        //then
+        assertTrue(delegate.statementEvaluated);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void regular_failing_test() throws Throwable {
+        //when
+        rule.apply(new Statement() {
+            public void evaluate() throws Throwable {
+                throw new IllegalArgumentException();
+            }
+        }, mock(FrameworkMethod.class), this).evaluate();
+    }
+
+    @Test public void rule_threw_exception() throws Throwable {
+        //expect
+        rule.expectFailure(AssertionError.class, "x");
+
+        //when
+        rule.apply(new Statement() {
+            public void evaluate() throws Throwable {
+                throw new AssertionError("x");
+            }
+        }, mock(FrameworkMethod.class), this).evaluate();
+    }
+
+    @Test public void expected_exception_but_no_exception() throws Throwable {
+        //expect
+        rule.expectFailure(AssertionError.class, "x");
+
+        //when
+        try {
+            rule.apply(new Statement() {
+                public void evaluate() throws Throwable {
+                    //all good
+                }
+            }, mock(FrameworkMethod.class), this).evaluate();
+            fail();
+
+        //then
+        } catch (SafeJUnitRule.ExpectedThrowableNotReported t) {
+            //yup, expected
+        }
+    }
+
+    @Test public void expected_exception_message_did_not_match() throws Throwable {
+        //expect
+        rule.expectFailure(AssertionError.class, "FOO");
+
+        //when
+        try {
+            rule.apply(new Statement() {
+                public void evaluate() throws Throwable {
+                    throw new AssertionError("BAR");
+                }
+            }, mock(FrameworkMethod.class), this).evaluate();
+            fail();
+        } catch (AssertionError throwable) {
+            Assertions.assertThat(throwable).hasMessageContaining("Expecting message");
+        }
+    }
+
+    @Test public void expected_exception_type_did_not_match() throws Throwable {
+        //expect
+        rule.expectFailure(AssertionError.class, "x");
+
+        //when
+        try {
+            rule.apply(new Statement() {
+                public void evaluate() throws Throwable {
+                    throw new RuntimeException("x");
+                }
+            }, mock(FrameworkMethod.class), this).evaluate();
+            fail();
+        } catch (AssertionError throwable) {
+            Assertions.assertThat(throwable).hasMessageContaining("but was instance of");
+        }
+    }
+
+    @Test public void expected_exception_assert_did_not_match() throws Throwable {
+        //expect
+        rule.expectFailure(new SafeJUnitRule.FailureAssert() {
+            public void doAssert(Throwable t) {
+                throw new AssertionError("x");
+            }
+        });
+
+        //when
+        try {
+            rule.apply(new Statement() {
+                public void evaluate() throws Throwable {
+                    throw new RuntimeException();
+                }
+            }, mock(FrameworkMethod.class), this).evaluate();
+            fail();
+        } catch (AssertionError throwable) {
+            assertEquals(throwable.getMessage(), "x");
+        }
+    }
+
+    private static class MethodRuleStub implements MethodRule {
+        private boolean statementEvaluated;
+        public Statement apply(final Statement base, FrameworkMethod method, Object target) {
+            return new Statement() {
+                public void evaluate() throws Throwable {
+                    statementEvaluated = true;
+                    base.evaluate();
+                }
+            };
+        }
+    }
+}
diff --git a/src/test/java/org/mockitoutil/SimpleClassGenerator.java b/src/test/java/org/mockitoutil/SimpleClassGenerator.java
new file mode 100644
index 0000000..0ad4785
--- /dev/null
+++ b/src/test/java/org/mockitoutil/SimpleClassGenerator.java
@@ -0,0 +1,19 @@
+package org.mockitoutil;
+
+import org.objectweb.asm.ClassWriter;
+
+import static org.objectweb.asm.Opcodes.*;
+
+public class SimpleClassGenerator {
+
+    public static byte[] makeMarkerInterface(String qualifiedName) {
+        String relativePath = qualifiedName.replace('.', '/');
+
+        ClassWriter cw = new ClassWriter(0);
+        cw.visit(V1_6, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, relativePath, null, "java/lang/Object", null);
+        cw.visitEnd();
+
+        return cw.toByteArray();
+    }
+
+}
diff --git a/src/test/java/org/mockitoutil/SimplePerRealmReloadingClassLoader.java b/src/test/java/org/mockitoutil/SimplePerRealmReloadingClassLoader.java
new file mode 100644
index 0000000..05a43f1
--- /dev/null
+++ b/src/test/java/org/mockitoutil/SimplePerRealmReloadingClassLoader.java
@@ -0,0 +1,118 @@
+package org.mockitoutil;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * Custom classloader to load classes in hierarchic realm.
+ *
+ * Each class can be reloaded in the realm if the LoadClassPredicate says so.
+ */
+public class SimplePerRealmReloadingClassLoader extends URLClassLoader {
+
+    private final Map<String,Class<?>> classHashMap = new HashMap<String, Class<?>>();
+    private ReloadClassPredicate reloadClassPredicate;
+
+    public SimplePerRealmReloadingClassLoader(ReloadClassPredicate reloadClassPredicate) {
+        super(getPossibleClassPathsUrls());
+        this.reloadClassPredicate = reloadClassPredicate;
+    }
+
+    public SimplePerRealmReloadingClassLoader(ClassLoader parentClassLoader, ReloadClassPredicate reloadClassPredicate) {
+        super(getPossibleClassPathsUrls(), parentClassLoader);
+        this.reloadClassPredicate = reloadClassPredicate;
+    }
+
+    private static URL[] getPossibleClassPathsUrls() {
+        return new URL[]{
+                obtainClassPath(),
+                obtainClassPath("org.mockito.Mockito"),
+                obtainClassPath("net.bytebuddy.ByteBuddy")
+        };
+    }
+
+    private static URL obtainClassPath() {
+        String className = SimplePerRealmReloadingClassLoader.class.getName();
+        return obtainClassPath(className);
+    }
+
+    private static URL obtainClassPath(String className) {
+        String path = className.replace('.', '/') + ".class";
+        String url = SimplePerRealmReloadingClassLoader.class.getClassLoader().getResource(path).toExternalForm();
+
+        try {
+            return new URL(url.substring(0, url.length() - path.length()));
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("Classloader couldn't obtain a proper classpath URL", e);
+        }
+    }
+
+
+
+    @Override
+    public Class<?> loadClass(String qualifiedClassName) throws ClassNotFoundException {
+        if(reloadClassPredicate.acceptReloadOf(qualifiedClassName)) {
+            // return customLoadClass(qualifiedClassName);
+//            Class<?> loadedClass = findLoadedClass(qualifiedClassName);
+            if(!classHashMap.containsKey(qualifiedClassName)) {
+                Class<?> foundClass = findClass(qualifiedClassName);
+                saveFoundClass(qualifiedClassName, foundClass);
+                return foundClass;
+            }
+
+            return classHashMap.get(qualifiedClassName);
+        }
+        return useParentClassLoaderFor(qualifiedClassName);
+    }
+
+    private void saveFoundClass(String qualifiedClassName, Class<?> foundClass) {
+        classHashMap.put(qualifiedClassName, foundClass);
+    }
+
+
+    private Class<?> useParentClassLoaderFor(String qualifiedName) throws ClassNotFoundException {
+        return super.loadClass(qualifiedName);
+    }
+
+
+    public Object doInRealm(String callableCalledInClassLoaderRealm) throws Exception {
+        ClassLoader current = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(this);
+            Object instance = this.loadClass(callableCalledInClassLoaderRealm).getConstructor().newInstance();
+            if (instance instanceof Callable) {
+                Callable<?> callableInRealm = (Callable<?>) instance;
+                return callableInRealm.call();
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(current);
+        }
+        throw new IllegalArgumentException("qualified name '" + callableCalledInClassLoaderRealm + "' should represent a class implementing Callable");
+    }
+
+
+    public Object doInRealm(String callableCalledInClassLoaderRealm, Class<?>[] argTypes, Object[] args) throws Exception {
+        ClassLoader current = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(this);
+            Object instance = this.loadClass(callableCalledInClassLoaderRealm).getConstructor(argTypes).newInstance(args);
+            if (instance instanceof Callable) {
+                Callable<?> callableInRealm = (Callable<?>) instance;
+                return callableInRealm.call();
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(current);
+        }
+
+        throw new IllegalArgumentException("qualified name '" + callableCalledInClassLoaderRealm + "' should represent a class implementing Callable");
+    }
+
+
+    public interface ReloadClassPredicate {
+        boolean acceptReloadOf(String qualifiedName);
+    }
+}
diff --git a/src/test/java/org/mockitoutil/SimpleSerializationUtil.java b/src/test/java/org/mockitoutil/SimpleSerializationUtil.java
new file mode 100644
index 0000000..d32d1e0
--- /dev/null
+++ b/src/test/java/org/mockitoutil/SimpleSerializationUtil.java
@@ -0,0 +1,33 @@
+package org.mockitoutil;
+
+import java.io.*;
+
+import static junit.framework.TestCase.assertNotNull;
+
+public abstract class SimpleSerializationUtil {
+
+    //TODO use widely
+    @SuppressWarnings("unchecked")
+    public static <T> T serializeAndBack(T obj) throws Exception {
+        ByteArrayOutputStream os = serializeMock(obj);
+        return (T) deserializeMock(os, Object.class);
+    }
+
+    public static <T> T deserializeMock(ByteArrayOutputStream serialized, Class<T> type) throws IOException,
+            ClassNotFoundException {
+        InputStream unserialize = new ByteArrayInputStream(serialized.toByteArray());
+        return deserializeMock(unserialize, type);
+    }
+
+    public static <T> T deserializeMock(InputStream unserialize, Class<T> type) throws IOException, ClassNotFoundException {
+        Object readObject = new ObjectInputStream(unserialize).readObject();
+        assertNotNull(readObject);
+        return type.cast(readObject);
+    }
+
+    public static ByteArrayOutputStream serializeMock(Object mock) throws IOException {
+        ByteArrayOutputStream serialized = new ByteArrayOutputStream();
+        new ObjectOutputStream(serialized).writeObject(mock);
+        return serialized;
+    }
+}
diff --git a/src/test/java/org/mockitoutil/Stopwatch.java b/src/test/java/org/mockitoutil/Stopwatch.java
new file mode 100644
index 0000000..a9258e8
--- /dev/null
+++ b/src/test/java/org/mockitoutil/Stopwatch.java
@@ -0,0 +1,65 @@
+package org.mockitoutil;
+
+import static java.lang.String.format;
+import static java.lang.System.nanoTime;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.concurrent.TimeUnit;
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+/**
+ * This class can be uses as stopwatch to assert that a given time is elapsed or not.
+ */
+public class Stopwatch {
+
+    /**
+     * The start time in nano seconds or <code>null</code> if this stop watch was not started yet
+     */
+    private Long startNanos = null;
+
+    /**
+     * To create an instance use {@link #createNotStarted()}
+     */
+    private Stopwatch() {
+    }
+
+    /**
+     * Return a new and not started {@link Stopwatch}.
+     */
+    public static Stopwatch createNotStarted() {
+        return new Stopwatch();
+    }
+
+    public void start() {
+        if (startNanos != null)
+            throw new IllegalStateException("This stop watch is already started!");
+
+        startNanos = nanoTime();
+    }
+
+    public void assertElapsedTimeIsMoreThan(long expected, TimeUnit unit) {
+        long elapsedNanos = elapsedNanos();
+        long expectedNanos = unit.toNanos(expected);
+
+        if (elapsedNanos <= expectedNanos)
+            fail("Expected that more than %dms elapsed! But was: %dms", expectedNanos, elapsedNanos);
+    }
+
+    public void assertElapsedTimeIsLessThan(long expected, TimeUnit unit) {
+        long elapsedNanos = elapsedNanos();
+        long expectedNanos = unit.toNanos(expected);
+
+        if (elapsedNanos >= expectedNanos)
+            fail("Expected that less than %dms elapsed! But was: %dms", expectedNanos, elapsedNanos);
+    }
+
+    private long elapsedNanos() {
+        if (startNanos == null)
+            throw new IllegalStateException("This stop watch is not started!");
+        return nanoTime() - startNanos;
+    }
+
+    private static void fail(String message, long expectedNanos, long elapsedNanos) {
+        throw new MockitoAssertionError(format(message, NANOSECONDS.toMillis(expectedNanos), NANOSECONDS.toMillis(elapsedNanos)));
+    }
+}
diff --git a/src/test/java/org/mockitoutil/TestBase.java b/src/test/java/org/mockitoutil/TestBase.java
new file mode 100644
index 0000000..464e2d5
--- /dev/null
+++ b/src/test/java/org/mockitoutil/TestBase.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockitoutil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.MockitoAnnotations;
+import org.mockito.StateMaster;
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.configuration.ConfigurationAccess;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.internal.invocation.InvocationImpl;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.SerializableMethod;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockito.invocation.Invocation;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import static org.mockito.Mockito.mock;
+
+/**
+ * the easiest way to make sure that tests clean up invalid state is to require
+ * valid state for all tests.
+ */
+public class TestBase {
+
+    @After
+    public void cleanUpConfigInAnyCase() {
+        ConfigurationAccess.getConfig().overrideCleansStackTrace(false);
+        ConfigurationAccess.getConfig().overrideDefaultAnswer(null);
+        StateMaster state = new StateMaster();
+        //catch any invalid state left over after test case run
+        //this way we can catch early if some Mockito operations leave weird state afterwards
+        state.validate();
+        //reset the state, especially, reset any ongoing stubbing for correct error messages of tests that assert unhappy paths
+        state.reset();
+    }
+
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public static void makeStackTracesClean() {
+        ConfigurationAccess.getConfig().overrideCleansStackTrace(true);
+    }
+
+    public void resetState() {
+        new StateMaster().reset();
+    }
+
+    public static Invocation getLastInvocation() {
+        return new MockitoCore().getLastInvocation();
+    }
+
+    protected static Invocation invocationOf(Class<?> type, String methodName, Object ... args) throws NoSuchMethodException {
+        Class<?>[] types = new Class<?>[args.length];
+        for (int i = 0; i < args.length; i++) {
+            types[i] = args[i].getClass();
+        }
+        return new InvocationImpl(mock(type), new SerializableMethod(type.getMethod(methodName,
+                types)), args, 1, null, new LocationImpl());
+    }
+
+    protected static Invocation invocationOf(Class<?> type, String methodName, RealMethod realMethod) throws NoSuchMethodException {
+        return new InvocationImpl(new Object(), new SerializableMethod(type.getMethod(methodName,
+                new Class<?>[0])), new Object[0], 1, realMethod, new LocationImpl());
+    }
+
+    protected static Invocation invocationAt(String location) {
+        return new InvocationBuilder().location(location).toInvocation();
+    }
+
+    protected static InvocationMatcher invocationMatcherAt(String location) {
+        return new InvocationBuilder().location(location).toInvocationMatcher();
+    }
+
+    protected String getStackTrace(Throwable e) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        e.printStackTrace(new PrintStream(out));
+        try {
+            out.close();
+        } catch (IOException ex) {}
+        return out.toString();
+    }
+
+    /**
+     * Filters out unwanted line numbers from provided stack trace String.
+     * This is useful for writing assertions for exception messages that contain line numbers.
+     *
+     * For example it turns:
+     * blah blah (UnusedStubsExceptionMessageTest.java:27)
+     * into:
+     * blah blah (UnusedStubsExceptionMessageTest.java:0)
+     */
+    public static String filterLineNo(String stackTrace) {
+        return stackTrace.replaceAll("(\\((\\w+\\.java):(\\d)+\\))", "($2:0)");
+    }
+}
diff --git a/src/test/java/org/mockitoutil/TestBaseTest.java b/src/test/java/org/mockitoutil/TestBaseTest.java
new file mode 100644
index 0000000..d8c94d9
--- /dev/null
+++ b/src/test/java/org/mockitoutil/TestBaseTest.java
@@ -0,0 +1,18 @@
+package org.mockitoutil;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestBaseTest extends TestBase {
+
+    @Test public void filters_line_no_from_stack_trace() {
+        assertEquals("", filterLineNo(""));
+        assertEquals("asdf", filterLineNo("asdf"));
+        assertEquals("asdf (FooBar.java:0) blah", filterLineNo("asdf (FooBar.java:23) blah"));
+        assertEquals("asdf\n(FooBar.java:0)\nblah", filterLineNo("asdf\n(FooBar.java:123123)\nblah"));
+        assertEquals("asdf\n(FooBar.java:0)\n(Xxx.java:0)blah", filterLineNo("asdf\n(FooBar.java:2)\n(Xxx.java:1)blah"));
+
+        assertEquals("asdf\n(FooBar.java:0)\nXxx.java:20)blah", filterLineNo("asdf\n(FooBar.java:2)\nXxx.java:20)blah"));
+    }
+}
diff --git a/src/test/java/org/mockitoutil/ThrowableAssert.java b/src/test/java/org/mockitoutil/ThrowableAssert.java
new file mode 100644
index 0000000..f5f6525
--- /dev/null
+++ b/src/test/java/org/mockitoutil/ThrowableAssert.java
@@ -0,0 +1,43 @@
+package org.mockitoutil;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Clean asserts for exception handling
+ */
+public class ThrowableAssert {
+
+    private Throwable reportedException;
+
+    private ThrowableAssert(Runnable runnable) {
+        try {
+            runnable.run();
+        } catch (Throwable t) {
+            this.reportedException = t;
+            return;
+        }
+        throw new AssertionError("Expected runnable to throw an exception but it didn't");
+    }
+
+    public ThrowableAssert throwsException(Class<? extends Throwable> exceptionType) {
+        if(!exceptionType.isInstance(reportedException)) {
+            throw new AssertionError("Exception should be of type: "
+                    + exceptionType.getSimpleName() + " but it was: "
+                    + reportedException.getClass().getSimpleName());
+        }
+        return this;
+    }
+
+    public ThrowableAssert throwsMessage(String exceptionMessage) {
+        assertEquals(exceptionMessage, reportedException.getMessage());
+        return this;
+    }
+
+    /**
+     * Executes provided runnable, expects it to throw an exception.
+     * Then, it offers ways to assert on the expected exception.
+     */
+    public static ThrowableAssert assertThat(Runnable runnable) {
+        return new ThrowableAssert(runnable);
+    }
+}
diff --git a/src/test/java/org/mockitoutil/VmArgAssumptions.java b/src/test/java/org/mockitoutil/VmArgAssumptions.java
new file mode 100644
index 0000000..29f9b96
--- /dev/null
+++ b/src/test/java/org/mockitoutil/VmArgAssumptions.java
@@ -0,0 +1,28 @@
+package org.mockitoutil;
+
+import java.lang.management.ManagementFactory;
+import java.util.List;
+
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+public class VmArgAssumptions {
+    public static void assumeVmArgPresent(String vmArg) {
+        assumeTrue(assertEnabled(vmArg));
+    }
+
+    public static void assumeVmArgNotPresent(String vmArg) {
+        assumeFalse(assertEnabled(vmArg));
+    }
+
+    private static boolean assertEnabled(String vmArg) {
+        List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
+        for (String inputArgument : inputArguments) {
+            if (inputArgument.contains(vmArg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/subprojects/android/android.gradle b/subprojects/android/android.gradle
new file mode 100644
index 0000000..e7f5268
--- /dev/null
+++ b/subprojects/android/android.gradle
@@ -0,0 +1,19 @@
+description = "Mockito for Android"
+
+ext {
+    artifactName = 'mockito-android'
+    bintrayAutoPublish = true
+    bintrayRepo = 'maven'
+    mavenCentralSync = false
+}
+
+apply from: "$rootDir/gradle/java-library.gradle"
+
+dependencies {
+    compile project.rootProject
+    compile "net.bytebuddy:byte-buddy-android:1.6.5"
+}
+
+apply from: "$rootDir/gradle/publishable-java-library.gradle"
+
+tasks.javadoc.enabled = false
diff --git a/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidByteBuddyMockMaker.java b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidByteBuddyMockMaker.java
new file mode 100644
index 0000000..1747358
--- /dev/null
+++ b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidByteBuddyMockMaker.java
@@ -0,0 +1,52 @@
+package org.mockito.android.internal.creation;
+
+import org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+import org.mockito.internal.util.Platform;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+
+import static org.mockito.internal.util.StringUtil.join;
+
+public class AndroidByteBuddyMockMaker implements MockMaker {
+
+    private final MockMaker delegate;
+
+    public AndroidByteBuddyMockMaker() {
+        if (Platform.isAndroid() || Platform.isAndroidMockMakerRequired()) {
+            delegate = new SubclassByteBuddyMockMaker(new AndroidLoadingStrategy());
+        } else {
+            new ConsoleMockitoLogger().log(join(
+                    "IMPORTANT NOTE FROM MOCKITO:",
+                    "",
+                    "You included the 'mockito-android' dependency in a non-Android environment.",
+                    "The Android mock maker was disabled. You should only include the latter in your 'androidTestCompile' configuration",
+                    "If disabling was a mistake, you can set the 'org.mockito.mock.android' property to 'true' to override this detection.",
+                    "",
+                    "Visit https://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.1 for more information"
+            ));
+            delegate = new SubclassByteBuddyMockMaker();
+        }
+    }
+
+    @Override
+    public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+        return delegate.createMock(settings, handler);
+    }
+
+    @Override
+    public MockHandler getHandler(Object mock) {
+        return delegate.getHandler(mock);
+    }
+
+    @Override
+    public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+        delegate.resetMock(mock, newHandler, settings);
+    }
+
+    @Override
+    public TypeMockability isTypeMockable(Class<?> type) {
+        return delegate.isTypeMockable(type);
+    }
+}
diff --git a/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidLoadingStrategy.java b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidLoadingStrategy.java
new file mode 100644
index 0000000..eeac19d
--- /dev/null
+++ b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidLoadingStrategy.java
@@ -0,0 +1,31 @@
+package org.mockito.android.internal.creation;
+
+import static org.mockito.internal.util.StringUtil.join;
+
+import java.io.File;
+import net.bytebuddy.android.AndroidClassLoadingStrategy;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.creation.bytebuddy.SubclassLoader;
+
+class AndroidLoadingStrategy implements SubclassLoader {
+
+    @Override
+    public ClassLoadingStrategy<ClassLoader> getStrategy(Class<?> mockFeatures) {
+        File target = AndroidTempFileLocator.target;
+        if (target == null) {
+            throw new MockitoException(join(
+                    "Could not look up implicit location for storing generated classes",
+                    "",
+                    "You can configure an explicit location by setting the system property",
+                    "'org.mockito.android.target' to a folder for storing generated class files",
+                    "This location must be in private scope for most API versions, for example:",
+                    "",
+                    "MyActivity.this.getDir(\"target\", Context.MODE_PRIVATE)",
+                    "or",
+                    "getInstrumentation().getTargetContext().getCacheDir().getPath()"
+            ));
+        }
+        return new AndroidClassLoadingStrategy.Injecting(target);
+    }
+}
diff --git a/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java
new file mode 100644
index 0000000..1e1dbb7
--- /dev/null
+++ b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java
@@ -0,0 +1,93 @@
+package org.mockito.android.internal.creation;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+class AndroidTempFileLocator {
+
+    final static File target;
+
+    static {
+        File t = null;
+        try {
+            String user = System.getProperty("org.mockito.android.target");
+            if (user != null) {
+                t = new File(user);
+            }
+        } catch (Throwable ignored) {
+        }
+        if (t == null) {
+            try {
+                Class<?> clazz = Class.forName("android.support.test.InstrumentationRegistry");
+                Object context = clazz.getDeclaredMethod("getTargetContext").invoke(clazz);
+                t = (File) context.getClass().getMethod("getCacheDir").invoke(context);
+            } catch (Throwable ignored) {
+            }
+        }
+        if (t == null) {
+            try {
+                Class<?> clazz = Class.forName("dalvik.system.PathClassLoader");
+                Field pathField = clazz.getDeclaredField("path");
+                pathField.setAccessible(true);
+                String pathFromThisClassLoader = (String) pathField.get(AndroidTempFileLocator.class.getClassLoader());
+                File[] results = guessPath(pathFromThisClassLoader);
+                if (results.length > 0) {
+                    t = results[0];
+                }
+            } catch (Throwable ignored) {
+            }
+        }
+        target = t;
+    }
+
+    private static File[] guessPath(String input) {
+        List<File> results = new ArrayList<File>();
+        for (String potential : splitPathList(input)) {
+            if (!potential.startsWith("/data/app/")) {
+                continue;
+            }
+            int start = "/data/app/".length();
+            int end = potential.lastIndexOf(".apk");
+            if (end != potential.length() - 4) {
+                continue;
+            }
+            int dash = potential.indexOf("-");
+            if (dash != -1) {
+                end = dash;
+            }
+            String packageName = potential.substring(start, end);
+            File dataDir = new File("/data/data/" + packageName);
+            if (isWriteableDirectory(dataDir)) {
+                File cacheDir = new File(dataDir, "cache");
+                if (fileOrDirExists(cacheDir) || cacheDir.mkdir()) {
+                    if (isWriteableDirectory(cacheDir)) {
+                        results.add(cacheDir);
+                    }
+                }
+            }
+        }
+        return results.toArray(new File[results.size()]);
+    }
+
+    private static String[] splitPathList(String input) {
+        String trimmed = input;
+        if (input.startsWith("dexPath=")) {
+            int start = "dexPath=".length();
+            int end = input.indexOf(',');
+
+            trimmed = (end == -1) ? input.substring(start) : input.substring(start, end);
+        }
+
+        return trimmed.split(":");
+    }
+
+    private static boolean fileOrDirExists(File file) {
+        return file.exists();
+    }
+
+    private static boolean isWriteableDirectory(File file) {
+        return file.isDirectory() && file.canWrite();
+    }
+}
diff --git a/subprojects/android/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker b/subprojects/android/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..4c26e63
--- /dev/null
+++ b/subprojects/android/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+org.mockito.android.internal.creation.AndroidByteBuddyMockMaker
\ No newline at end of file