[med-svn] [libcofoja-java] 01/02: Imported Upstream version 1.1-r150

Andreas Tille tille at debian.org
Sat Mar 8 22:27:40 UTC 2014


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository libcofoja-java.

commit e43f28e2a16b800a606cef8a5f1ec354acd713c4
Author: Andreas Tille <tille at debian.org>
Date:   Sat Mar 8 23:25:56 2014 +0100

    Imported Upstream version 1.1-r150
---
 COPYING                                            | 165 ++++++
 README                                             | 136 +++++
 build.xml                                          | 257 +++++++++
 build/PreAgentAntTask.java                         |  81 +++
 default.properties                                 |  23 +
 script/cofojab.sh                                  |  94 +++
 script/cofojac.sh                                  | 133 +++++
 src/META-INF/MANIFEST.MF                           |   2 +
 .../services/javax.annotation.processing.Processor |   1 +
 .../google/java/contract/AllowUnusedImport.java    |  39 ++
 .../java/contract/ContractAssertionError.java      | 111 ++++
 .../google/java/contract/ContractEnvironment.java  | 191 +++++++
 .../contract/ContractEnvironmentConfigurator.java  |  38 ++
 src/com/google/java/contract/Ensures.java          |  75 +++
 src/com/google/java/contract/Invariant.java        |  49 ++
 src/com/google/java/contract/InvariantError.java   |  53 ++
 .../google/java/contract/PostconditionError.java   |  53 ++
 .../google/java/contract/PreconditionError.java    |  55 ++
 src/com/google/java/contract/Requires.java         |  51 ++
 .../google/java/contract/SpecificationError.java   |  36 ++
 src/com/google/java/contract/ThrowEnsures.java     |  65 +++
 .../contract/core/agent/ActivationRuleManager.java | 124 ++++
 .../core/agent/AgentContractEnvironment.java       |  95 ++++
 .../contract/core/agent/ClassContractHandle.java   |  59 ++
 .../java/contract/core/agent/ContractAnalyzer.java | 288 ++++++++++
 .../core/agent/ContractClassFileTransformer.java   | 408 +++++++++++++
 .../core/agent/ContractFixingClassAdapter.java     |  94 +++
 .../java/contract/core/agent/ContractHandle.java   | 127 +++++
 .../core/agent/ContractMethodSignature.java        |  61 ++
 .../core/agent/ContractMethodSignatures.java       | 166 ++++++
 .../contract/core/agent/HelperClassAdapter.java    | 104 ++++
 .../core/agent/LineNumberingClassAdapter.java      |  69 +++
 .../core/agent/LineNumberingMethodAdapter.java     | 110 ++++
 .../contract/core/agent/MethodContractHandle.java  |  68 +++
 .../google/java/contract/core/agent/PreMain.java   | 232 ++++++++
 .../core/agent/SpecificationClassAdapter.java      | 123 ++++
 .../core/agent/SpecificationMethodAdapter.java     | 632 +++++++++++++++++++++
 .../contract/core/apt/AbstractTypeBuilder.java     | 292 ++++++++++
 .../contract/core/apt/AnnotationProcessor.java     | 408 +++++++++++++
 .../contract/core/apt/AnnotationSourceInfo.java    |  94 +++
 .../contract/core/apt/ClassContractCreator.java    | 121 ++++
 .../java/contract/core/apt/ContractCreation.java   | 528 +++++++++++++++++
 .../contract/core/apt/ContractCreationTrait.java   | 111 ++++
 .../core/apt/ContractExpressionCreationTrait.java  |  73 +++
 .../core/apt/ContractExpressionTransformer.java    | 369 ++++++++++++
 .../java/contract/core/apt/ContractFinder.java     | 175 ++++++
 .../contract/core/apt/ContractJavaCompiler.java    | 124 ++++
 .../contract/core/apt/ContractJavaFileManager.java | 127 +++++
 .../java/contract/core/apt/ContractWriter.java     | 629 ++++++++++++++++++++
 .../java/contract/core/apt/DiagnosticManager.java  | 525 +++++++++++++++++
 .../java/contract/core/apt/FactoryUtils.java       | 167 ++++++
 .../google/java/contract/core/apt/JavacUtils.java  | 131 +++++
 .../contract/core/apt/MethodContractCreator.java   | 359 ++++++++++++
 .../core/apt/SimpleContractCreationTrait.java      |  80 +++
 .../contract/core/apt/SourceDependencyParser.java  | 212 +++++++
 .../java/contract/core/apt/SourcePreprocessor.java | 122 ++++
 .../java/contract/core/apt/SuperCallBuilder.java   |  95 ++++
 .../google/java/contract/core/apt/TypeBuilder.java | 444 +++++++++++++++
 .../google/java/contract/core/apt/TypeFactory.java |  79 +++
 .../google/java/contract/core/model/ClassName.java | 311 ++++++++++
 .../core/model/ContractAnnotationModel.java        | 223 ++++++++
 .../java/contract/core/model/ContractKind.java     | 249 ++++++++
 .../contract/core/model/ContractMethodModel.java   | 243 ++++++++
 .../java/contract/core/model/ContractVariance.java |  42 ++
 .../java/contract/core/model/ElementKind.java      | 195 +++++++
 .../java/contract/core/model/ElementModel.java     | 272 +++++++++
 .../java/contract/core/model/ElementModifier.java  | 189 ++++++
 .../java/contract/core/model/ElementVisitor.java   |  59 ++
 .../contract/core/model/GenericElementModel.java   |  90 +++
 .../java/contract/core/model/HelperTypeModel.java  |  76 +++
 .../java/contract/core/model/MethodModel.java      | 229 ++++++++
 .../contract/core/model/QualifiedElementModel.java | 108 ++++
 .../google/java/contract/core/model/TypeModel.java | 276 +++++++++
 .../google/java/contract/core/model/TypeName.java  |  62 ++
 .../java/contract/core/model/VariableModel.java    |  84 +++
 .../contract/core/runtime/BlacklistManager.java    |  75 +++
 .../contract/core/runtime/ContractContext.java     | 113 ++++
 .../contract/core/runtime/ContractRuntime.java     |  61 ++
 .../core/runtime/RuntimeContractEnvironment.java   | 108 ++++
 .../java/contract/core/util/BalancedTokenizer.java | 146 +++++
 .../google/java/contract/core/util/DebugUtils.java | 138 +++++
 .../java/contract/core/util/ElementScanner.java    |  75 +++
 .../google/java/contract/core/util/Elements.java   | 132 +++++
 .../contract/core/util/EmptyElementVisitor.java    |  53 ++
 .../java/contract/core/util/JavaTokenizer.java     | 312 ++++++++++
 .../google/java/contract/core/util/JavaUtils.java  | 556 ++++++++++++++++++
 .../contract/core/util/LineNumberingTokenizer.java |  72 +++
 .../google/java/contract/core/util/PatternMap.java | 218 +++++++
 .../java/contract/core/util/PushbackTokenizer.java | 116 ++++
 .../java/contract/core/util/SyntheticJavaFile.java |  91 +++
 src/com/google/java/contract/util/Iterables.java   |  72 +++
 src/com/google/java/contract/util/Objects.java     |  40 ++
 src/com/google/java/contract/util/Predicate.java   |  35 ++
 src/com/google/java/contract/util/Predicates.java  | 327 +++++++++++
 .../java/contract/examples/ArrayListStack.java     |  60 ++
 test/com/google/java/contract/examples/Stack.java  |  65 +++
 test/com/google/java/contract/tests/Cofoja.java    |  33 ++
 .../java/contract/tests/ConstantContracts.java     |  70 +++
 .../java/contract/tests/ConstantContractsTest.java |  94 +++
 .../java/contract/tests/ConstructorTest.java       | 160 ++++++
 .../contract/tests/ContractedAnnotationTest.java   | 113 ++++
 .../java/contract/tests/ContractedClass.java       |  27 +
 .../google/java/contract/tests/EmptyContracts.java |  39 ++
 .../contract/tests/EnclosedExtendsEnclosing.java   |  36 ++
 .../tests/EnclosedExtendsEnclosingNoContracts.java |  33 ++
 .../tests/EnclosedExtendsEnclosingTest.java        |  50 ++
 test/com/google/java/contract/tests/EnumTest.java  |  70 +++
 .../contract/tests/ExceptionInPredicateTest.java   |  56 ++
 .../java/contract/tests/FinalFieldsTest.java       | 119 ++++
 .../google/java/contract/tests/GenericsTest.java   | 204 +++++++
 .../java/contract/tests/InheritanceTest.java       | 296 ++++++++++
 .../java/contract/tests/InnerAnnotationTest.java   |  45 ++
 .../java/contract/tests/MemberContractsTest.java   | 168 ++++++
 .../java/contract/tests/NestedClassTest.java       | 120 ++++
 .../google/java/contract/tests/PatternMapTest.java |  90 +++
 .../google/java/contract/tests/PublicCallTest.java | 113 ++++
 .../google/java/contract/tests/ReturnTypeTest.java | 151 +++++
 .../contract/tests/SelectiveContractsTest.java     | 160 ++++++
 .../contract/tests/SeparateGenericSuperclass.java  |  34 ++
 .../tests/SeparateGenericSuperclassTest.java       |  48 ++
 .../java/contract/tests/SeparateInterface.java     |  40 ++
 .../java/contract/tests/SeparateInterfaceTest.java | 105 ++++
 .../tests/SeparateInvariantSuperclass.java         |  38 ++
 .../tests/SeparateInvariantSuperclassTest.java     |  54 ++
 .../tests/SeparateMethodContractSuperclass.java    |  31 +
 .../SeparateMethodContractSuperclassTest.java      |  54 ++
 .../google/java/contract/tests/SimpleMathTest.java | 208 +++++++
 test/com/google/java/contract/tests/StackTest.java | 190 +++++++
 .../google/java/contract/tests/VariadicTest.java   | 118 ++++
 .../google/java/contract/tests/selective/a/A.java  |  24 +
 .../java/contract/tests/selective/a/x/X.java       |  24 +
 .../java/contract/tests/selective/a/x/X1.java      |  24 +
 .../google/java/contract/tests/selective/b/B.java  |  24 +
 .../java/contract/tests/selective/b/y/Y.java       |  24 +
 134 files changed, 18593 insertions(+)

diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..3462706
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
\ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..29adefa
--- /dev/null
+++ b/README
@@ -0,0 +1,136 @@
+Contracts for Java is a contract programming framework for Java, which
+uses annotation processing and bytecode instrumentation to provide
+run-time checking.
+
+
+1. DEPENDENCIES
+
+Contracts fo Java requires Java version 6 for annotation processing
+and bytecode instrumentation. The bytecode rewriter depends on the ASM
+bytecode manipulation library, version 4.x or higher.
+
+Since the Java agent rewrites bytecode in order to inject contracts
+into the loaded code, the ASM library needs to be available in the
+class path at run time if contract checking is enforced through the
+agent. Pre-contracted class files do not need the ASM library or the
+agent to run with contracts enabled.
+
+
+2. CONFIGURATION
+
+In order for the build script to run properly, you must at least
+specify the correct path to Cofoja's dependencies in your local build
+properties file:
+
+  ./local.properties
+
+This file does not exist by default; you can either create it or start
+from a copy of the default configuration file:
+
+  ./default.properties
+
+That file also contains all user-settable properties with their
+descriptions and default values. Once you're done, set the following
+property to true to let Ant run:
+
+  configured=true
+
+
+3. QUICK START
+
+To build a JAR file containing all Cofoja classes, run:
+
+  ant dist
+
+The JAR file will be located at:
+
+  ./dist/lib/cofoja-<version>.jar
+
+It can be used both as a Java agent and annotation processor and
+should be added to your class path.
+
+To compile code with contract annotations, run:
+
+  javac -processor com.google.java.contract.core.apt.AnnotationProcessor <someclass>.java
+
+To execute code compiled with contract checking enabled, make sure the
+generated files (additional .class and .contracts files) are in your
+class path, and run:
+
+  java -javaagent:path/to/cofoja-<version>.jar <someclass>
+
+
+4. ADVANCED BUILD
+
+Contracts for Java is annotated with its own contracts, which can be
+compiled, tested and bundled into the result JAR file so it checks its
+own contracts when compiling and checking your program's contracts!
+
+Please note that running such a build will necessarily be slower than
+running an unchecked version of Contracts for Java, but is a great way
+for you to contribute to the project by helping exercise its own
+capabilities while using it.
+
+To build a contracted version of Contracts for Java, you need to have
+a Cofoja JAR file ready first (see previous section; or you could
+reuse one you've built with a previous run of this bootstrap
+process). Copy the JAR file to:
+
+  ./build/bootstrap.jar
+
+Then run:
+
+  ant bootstrap
+
+Once the contracted version is complete, you can run the test suite
+with:
+
+  ant test
+
+Aside from self-contracted builds, Cofoja JAR files bundled with ASM
+library classes can also be produced, for the sake of easier
+distribution:
+
+  ant -Dasmjar=path/to/asm-all-<version>.jar dist
+
+
+5. USAGE
+
+Contracts for Java consists of an annotation processor, an
+instrumentation agent, as well as an offline bytecode rewriter. The
+annotation processor compiles annotations into separate contract class
+files. The instrumentation agent weaves these contract files with the
+real classes before they are loaded into the JVM. Alternatively, the
+offline bytecode rewriter can be used to produce pre-weaved class
+files that can be directly deployed without any Cofoja dependency.
+
+The following instructions assume that you have the Cofoja and ASM JAR
+files in your class path.
+
+The annotation processor's entry point is (for use with the -processor
+javac option):
+
+  com.google.java.contract.core.apt.AnnotationProcessor
+
+The Java agent can be invoked from the compiled JAR file (for use with
+the -javaagent java option):
+
+  ./dist/cofoja-<version>.jar
+
+The offline instrumenter can be run with:
+
+  java -Dcom.google.java.contract.classoutput=<outdir> \
+    com.google.java.contract.core.agent.PreMain <someclass>.class
+
+Please refer to the official online documentation for more
+information:
+
+  http://code.google.com/p/cofoja/wiki/QuickReference
+
+
+6. BUGS
+
+Contracts for Java is a very young project. Please help us make it
+better by reporting bugs and posting patches at:
+
+  http://code.google.com/p/cofoja/issues/
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..9edd215
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,257 @@
+<project name="Cofoja" default="dist" basedir=".">
+  <!-- Configurable properties. -->
+  <property file="local.properties" />
+  <property file="default.properties" />
+
+  <!-- Private properties. -->
+
+  <property name="src.dir" location="src" />
+  <property name="test.dir" location="test" />
+  <property name="build.dir" location="build" />
+  <property name="obj.dir" location="obj" />
+  <property name="dist.dir" location="dist" />
+
+  <property name="manifest.path"
+            value="${src.dir}/META-INF/MANIFEST.MF" />
+  <property name="apt.class"
+            value="com.google.java.contract.core.apt.AnnotationProcessor" />
+  <property name="test.configurator.class"
+            value="com.google.java.contract.tests.Cofoja" />
+
+  <path id="base.class.path">
+    <pathelement path="${asm.jar}" />
+    <pathelement path="${tools.jar}" />
+  </path>
+
+  <path id="test.class.path">
+    <path refid="base.class.path" />
+    <pathelement path="${junit.jar}" />
+  </path>
+
+  <!-- Build macros. -->
+
+  <presetdef name="ujavac">
+    <javac encoding="utf-8" debug="${debug}" includeantruntime="false" />
+  </presetdef>
+
+  <macrodef name="checkjar">
+    <attribute name="label" />
+    <attribute name="property" />
+    <sequential>
+      <condition property="@{property}.notfound"
+                 value="no such file: "
+                 else="">
+        <not>
+          <available file="${@{property}}" />
+        </not>
+      </condition>
+      <echo message="@{label}${@{property}.notfound}${@{property}}" />
+    </sequential>
+  </macrodef>
+
+  <macrodef name="requirejar">
+    <attribute name="property" />
+    <sequential>
+      <fail message="Cannot find '${@{property}}'. Please link to the appropriate file or set the '@{property}' property to suit your environment. Consult the 'README' file for more information.">
+        <condition>
+          <not>
+            <equals arg1="${@{property}.notfound}" arg2="" />
+          </not>
+        </condition>
+      </fail>
+    </sequential>
+  </macrodef>
+
+  <macrodef name="barejar">
+    <attribute name="jarfile" />
+    <attribute name="basedir" />
+    <sequential>
+      <jar jarfile="@{jarfile}"
+           basedir="@{basedir}"
+           manifest="${manifest.path}">
+        <service type="javax.annotation.processing.Processor"
+                 provider="${apt.class}" />
+      </jar>
+    </sequential>
+  </macrodef>
+
+  <macrodef name="fulljar">
+    <attribute name="jarfile" />
+    <attribute name="barejarfile" />
+    <sequential>
+      <jar jarfile="@{jarfile}"
+           manifest="${manifest.path}">
+        <service type="javax.annotation.processing.Processor"
+                 provider="${apt.class}" />
+        <zipfileset includes="**/*.class"
+                    src="@{barejarfile}" />
+        <zipfileset includes="**/*.class" src="${asm.jar}" />
+      </jar>
+    </sequential>
+  </macrodef>
+
+  <macrodef name="bootstrapcomp">
+    <attribute name="stage" />
+    <attribute name="bootstrappath" />
+    <sequential>
+      <mkdir dir="${obj.dir}/tmp@{stage}" />
+      <mkdir dir="${obj.dir}/stage@{stage}" />
+      <ujavac srcdir="${src.dir}" destdir="${obj.dir}/tmp@{stage}" debug="true">
+        <classpath refid="base.class.path" />
+        <compilerarg value="-processorpath" />
+        <compilerarg value="@{bootstrappath}:${asm.jar}" />
+        <compilerarg value="-processor" />
+        <compilerarg value="${apt.class}" />
+      </ujavac>
+      <cofojab srcdir="${obj.dir}/tmp@{stage}"
+               destdir="${obj.dir}/stage@{stage}" />
+    </sequential>
+  </macrodef>
+
+  <!-- Initialization. -->
+
+  <target name="configure">
+    <echo message="Configuration" />
+    <echo message="-------------" />
+    <checkjar label="ASM JAR:       " property="asm.jar" />
+    <checkjar label="JUnit JAR:     " property="junit.jar" />
+    <checkjar label="JDK Tools JAR: " property="tools.jar" />
+    <checkjar label="Bootstrap JAR: " property="bootstrap.jar" />
+    <echo message="Snapshot:      ${snapshot}" />
+    <echo message="Debug:         ${debug}" />
+  </target>
+
+  <target name="init" depends="configure">
+    <requirejar property="asm.jar" />
+    <requirejar property="tools.jar" />
+
+    <tstamp />
+    <condition property="cofoja.version"
+               value="${version}-${DSTAMP}"
+               else="${version}">
+      <equals arg1="${snapshot}" arg2="true" />
+    </condition>
+    <property name="cofoja.jar"
+              value="${dist.dir}/cofoja-${cofoja.version}.jar" />
+    <property name="cofoja.bare.jar"
+              value="${dist.dir}/cofoja-${cofoja.version}-bare.jar" />
+    <property name="cofoja.contracted.jar"
+              value="${dist.dir}/ccofoja-${cofoja.version}.jar" />
+    <property name="cofoja.contracted.bare.jar"
+              value="${dist.dir}/ccofoja-${cofoja.version}-bare.jar" />
+
+    <mkdir dir="${obj.dir}" />
+    <mkdir dir="${dist.dir}" />
+  </target>
+
+  <!-- Simple build. -->
+
+  <target name="build" depends="init"
+          description="build class files">
+    <mkdir dir="${obj.dir}/bare" />
+    <ujavac srcdir="${src.dir}" destdir="${obj.dir}/bare">
+      <classpath refid="base.class.path" />
+    </ujavac>
+  </target>
+
+  <target name="dist" depends="build"
+          description="build JAR files for distribution">
+    <barejar jarfile="${cofoja.bare.jar}" basedir="${obj.dir}/bare" />
+    <fulljar jarfile="${cofoja.jar}" barejarfile="${cofoja.bare.jar}" />
+  </target>
+
+  <!-- Bootstrap. -->
+
+  <target name="antinit" depends="init">
+    <requirejar property="bootstrap.jar" />
+    <mkdir dir="${obj.dir}/build" />
+    <ujavac srcdir="${build.dir}" destdir="${obj.dir}/build">
+      <classpath>
+        <path refid="base.class.path" />
+        <pathelement path="${java.class.path}" />
+        <pathelement path="${bootstrap.jar}" />
+      </classpath>
+    </ujavac>
+    <taskdef name="cofojab" classname="PreAgentAntTask"
+             classpath="${obj.dir}/build:${bootstrap.jar}:${asm.jar}" />
+  </target>
+
+  <target name="stage0" depends="antinit">
+    <bootstrapcomp stage="0" bootstrappath="${bootstrap.jar}" />
+  </target>
+
+  <target name="stage1" depends="stage0">
+    <bootstrapcomp stage="1" bootstrappath="${obj.dir}/stage0" />
+  </target>
+
+  <target name="stage2" depends="stage1">
+    <bootstrapcomp stage="2" bootstrappath="${obj.dir}/stage1" />
+  </target>
+
+  <target name="bootstrap" depends="stage2"
+          description="build bootstrap-contracted JAR files">
+    <barejar jarfile="${cofoja.contracted.bare.jar}"
+             basedir="${obj.dir}/stage2" />
+    <fulljar jarfile="${cofoja.contracted.jar}"
+             barejarfile="${cofoja.contracted.bare.jar}" />
+  </target>
+
+  <!-- Tests. -->
+
+  <target name="buildtest1" depends="stage2">
+    <requirejar property="junit.jar" />
+    <mkdir dir="${obj.dir}/test" />
+    <ujavac srcdir="${test.dir}" destdir="${obj.dir}/test">
+      <classpath>
+        <path refid="test.class.path" />
+        <pathelement path="${obj.dir}/stage2" />
+      </classpath>
+      <compilerarg value="-processor" />
+      <compilerarg value="${apt.class}" />
+      <include name="**/SeparateGenericSuperclass.java" />
+      <include name="**/SeparateInterface.java" />
+    </ujavac>
+  </target>
+
+  <target name="buildtest2" depends="buildtest1,stage2">
+    <ujavac srcdir="${test.dir}" destdir="${obj.dir}/test">
+      <classpath>
+        <path refid="test.class.path" />
+        <pathelement path="${obj.dir}/stage2" />
+        <pathelement path="${obj.dir}/test" />
+      </classpath>
+      <compilerarg value="-processor" />
+      <compilerarg value="${apt.class}" />
+      <compilerarg value="-Acom.google.java.contract.dump=${obj.dir}/test/dump" />
+      <exclude name="**/SeparateGenericSuperclass.java" />
+      <exclude name="**/SeparateInterface.java" />
+    </ujavac>
+  </target>
+
+  <target name="test" depends="buildtest2,bootstrap"
+          description="run tests">
+    <junit printsummary="yes" haltonfailure="yes">
+      <classpath>
+        <path refid="test.class.path" />
+        <pathelement path="${obj.dir}/stage2" />
+        <pathelement location="${obj.dir}/test"/>
+      </classpath>
+      <jvmarg value="-javaagent:${cofoja.contracted.bare.jar}" />
+      <jvmarg value="-Dcom.google.java.contract.configurator=${test.configurator.class}" />
+      <formatter type="plain" />
+      <batchtest fork="yes" todir="${obj.dir}/test">
+        <fileset dir="${obj.dir}/test">
+          <include name="**/*Test.class"/>
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
+
+  <!-- Book-keeping. -->
+
+  <target name="clean"
+          description="remove generated files">
+    <delete dir="${obj.dir}" />
+    <delete dir="${dist.dir}" />
+  </target>
+</project>
diff --git a/build/PreAgentAntTask.java b/build/PreAgentAntTask.java
new file mode 100644
index 0000000..bdd3e86
--- /dev/null
+++ b/build/PreAgentAntTask.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+import com.google.java.contract.core.agent.PreMain;
+import com.google.java.contract.core.util.JavaUtils;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.taskdefs.MatchingTask;
+
+import java.io.File;
+import java.util.ArrayList;
+import javax.tools.JavaFileObject.Kind;
+
+public class PreAgentAntTask extends MatchingTask {
+  protected File srcdir;
+  protected File destdir;
+
+  public void setSrcdir(File srcdir) {
+    this.srcdir = srcdir;
+  }
+
+  public void setDestdir(File destdir) {
+    this.destdir = destdir;
+  }
+
+  public void execute() throws BuildException {
+    if (srcdir == null) {
+      throw new BuildException("missing required attribute \"srcdir\"");
+    }
+    if (destdir == null) {
+      throw new BuildException("missing required attribute \"destdir\"");
+    }
+
+    DirectoryScanner ds = getDirectoryScanner(srcdir);
+    try {
+      String[] srcs = ds.getIncludedFiles();
+      ArrayList<String> absSrcs = new ArrayList<String>();
+
+      for (String src : srcs) {
+        if (!src.toString().endsWith(Kind.CLASS.extension)) {
+          continue;
+        }
+        File srcFile = new File(srcdir + "/" + src);
+        File destFile = new File(destdir + "/" + src);
+        if (srcFile.lastModified() > destFile.lastModified()) {
+          absSrcs.add(srcFile.toString());
+        }
+      }
+
+      int n = absSrcs.size();
+      if (n > 0) {
+        System.out.println("Instrumenting " + n
+                           + " class file" + (n == 1 ? "" : "s")
+                           + " to " + destdir);
+        ClassLoader loader =
+            JavaUtils.getLoaderForPath(srcdir.toString(),
+                                       getClass().getClassLoader());
+        PreMain.instrument(absSrcs.toArray(new String[0]),
+                           destdir.toString(),
+                           loader);
+      }
+    } catch (Exception e) {
+      throw new BuildException(e);
+    }
+  }
+}
diff --git a/default.properties b/default.properties
new file mode 100644
index 0000000..a74d238
--- /dev/null
+++ b/default.properties
@@ -0,0 +1,23 @@
+## You can override the following properties by creating
+## a 'local.properties' configuration file.
+
+## Version information. Set 'snapshot' to false if you are building
+## a release.
+version=1.1
+snapshot=true
+debug=true
+
+## Location of an older build of Cofoja, for bootstrapping purposes.
+bootstrap.jar=build/bootstrap.jar
+
+## Location of dependency JAR files needed to build Cofoja. The
+## defaults assume the JAR files are in the 'build' subdirectory,
+## except for 'tools.jar', which is probably not what you want.
+asm.jar=build/asm.jar
+junit.jar=build/junit.jar
+tools.jar=${java.home}/../lib/tools.jar
+
+## If you use Maven, the following may help, instead.
+# maven.repo.dir=${user.home}/.m2/repository
+# asm.jar=${maven.repo.dir}/asm/asm-all/3.3.1/asm-all-3.3.1.jar
+# junit.jar=${maven.repo.dir}/junit/junit/4.8.2/junit-4.8.2.jar
diff --git a/script/cofojab.sh b/script/cofojab.sh
new file mode 100755
index 0000000..384457d
--- /dev/null
+++ b/script/cofojab.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+# Copyright 2010 Google Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+usage()
+{
+  cat <<EOF
+Usage: ${0##*/} [<options>] <file>[.class] ...
+Options:
+  -d <dir>               output class directory; if not specified, output
+                         class files are suffixed with .contracted
+  -java <java>           calls this instead of java
+  -jar <file>            specifies the JAR file that contains Contracts for Java
+  -configurator <class>  instantiates and calls this configurator
+  <file>[.class]         the class files to instrument; helper class
+                         files need not be specified explicitly
+EOF
+  exit
+}
+
+shellquote()
+{
+  echo "$1" | sed "s/'/'\\\\''/g"
+}
+
+JAVA=${JAVA:-java}
+
+configurator=
+jarfile=
+classoutput=
+files=
+
+if [ $# -eq 0 ]; then
+  usage
+fi
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -configurator)
+      shift
+      [ $# -eq 0 ] && usage
+      configurator="$1"
+      ;;
+    -d)
+      shift
+      [ $# -eq 0 ] && usage
+      classoutput="$1"
+      ;;
+    -jar)
+      shift
+      [ $# -eq 0 ] && usage
+      jarfile="$1"
+      ;;
+    -java)
+      shift
+      [ $# -eq 0 ] && usage
+      JAVA="$1"
+      ;;
+    *)
+      files="$files '$(shellquote "$1")'"
+  esac
+  shift
+done
+
+cmd=$JAVA
+if [ "$configurator" ]; then
+  cmd="$cmd -Dcom.google.java.contract.configurator=\"$configurator\""
+fi
+if [ "$jarfile" ]; then
+  if [ "$CLASSPATH" ]; then
+    export CLASSPATH=$jarfile:$CLASSPATH
+  else
+    export CLASSPATH=$jarfile:.
+  fi
+fi
+if [ "$classoutput" ]; then
+  cmd="$cmd -Dcom.google.java.contract.classoutput=\"$classoutput\""
+fi
+cmd="$cmd com.google.java.contract.core.agent.PreMain $files"
+
+eval "$cmd" || exit
diff --git a/script/cofojac.sh b/script/cofojac.sh
new file mode 100755
index 0000000..e7ede31
--- /dev/null
+++ b/script/cofojac.sh
@@ -0,0 +1,133 @@
+#!/bin/sh
+# Copyright 2010 Google Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+usage()
+{
+  cat <<EOF
+Usage: ${0##*/} [<options>] [<javac-option>] ... <source> ...
+Options:
+  -java <javac>   calls this instead of java
+  -javac <javac>  calls this instead of javac
+  -g:contracts    compiles debug contract code
+  -deps:none      skip source dependency preprocessing
+  -deps:only      stop after source dependency preprocessing
+  <javac-option>  passes argument to javac
+  <source>        source file
+EOF
+  exit
+}
+
+shellquote()
+{
+  echo "$1" | sed "s/'/'\\\\''/g"
+}
+
+JAVA=${JAVA:-java}
+JAVAC=${JAVAC:-javac}
+
+classpath=
+classoutput=
+debug=no
+passthrough=
+
+procapt=yes
+procdeps=yes
+
+if [ $# -eq 0 ]; then
+  usage
+fi
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -cp|-classpath)
+      shift
+      [ $# -eq 0 ] && usage
+      classpath="$1"
+      ;;
+    -d)
+      shift
+      [ $# -eq 0 ] && usage
+      classoutput="$1"
+      ;;
+    -deps:only)
+      procdeps=yes
+      procapt=no
+      ;;
+    -deps:none)
+      procdeps=no
+      ;;
+    -g:contracts)
+      debug=yes
+      ;;
+    -java)
+      shift
+      [ $# -eq 0 ] && usage
+      JAVA="$1"
+      ;;
+    -javac)
+      shift
+      [ $# -eq 0 ] && usage
+      JAVAC="$1"
+      ;;
+    *)
+      passthrough="$passthrough '$(shellquote "$1")'"
+  esac
+  shift
+done
+
+depsdir=
+if [ $procdeps = yes ]; then
+  cmd=$JAVA
+  if [ $procapt = yes ]; then
+    depsdir=$$.com.google.java.contract.d
+    mkdir "$depsdir"
+    cmd="$cmd -Dcom.google.java.contract.depsoutput=\"\$depsdir\""
+  elif [ "$classoutput" ]; then
+    cmd="$cmd -Dcom.google.java.contract.depsoutput=\"\$classoutput\""
+  fi
+  cmd="$cmd com.google.java.contract.core.apt.SourcePreprocessor $passthrough"
+
+  eval "$cmd" || exit
+fi
+
+if [ $procapt = yes ]; then
+  cmd=$JAVAC
+  if [ "$classpath" ]; then
+    cmd="$cmd -cp \"\$classpath\" -Acom.google.java.contract.classpath=\"\$classpath\""
+  fi
+  if [ "$classoutput" ]; then
+    cmd="$cmd -d \"\$classoutput\" -Acom.google.java.contract.classoutput=\"\$classoutput\""
+  fi
+  if [ $debug = yes ]; then
+    cmd="$cmd -Acom.google.java.contract.debug"
+  fi
+  if [ "$depsdir" ]; then
+    cmd="$cmd -Acom.google.java.contract.depspath=\"\$depsdir\""
+  fi
+  cmd="$cmd $passthrough"
+
+  eval "$cmd"
+  excode=$?
+
+  if [ "$depsdir" ]; then
+    rm -rf "$depsdir"
+  fi
+
+  if [ $excode -ne 0 ]; then
+    exit $excode
+  fi
+fi
diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..f255494
--- /dev/null
+++ b/src/META-INF/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Premain-Class: com.google.java.contract.core.agent.PreMain
diff --git a/src/META-INF/services/javax.annotation.processing.Processor b/src/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..76ff481
--- /dev/null
+++ b/src/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.google.java.contract.core.apt.AnnotationProcessor
diff --git a/src/com/google/java/contract/AllowUnusedImport.java b/src/com/google/java/contract/AllowUnusedImport.java
new file mode 100644
index 0000000..ab4191b
--- /dev/null
+++ b/src/com/google/java/contract/AllowUnusedImport.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * References a class so it is considered used by import statement
+ * cleaning tools. Such a class may be used only in contracts, which
+ * are not understood by such tools.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Target(ElementType.TYPE)
+ at Retention(RetentionPolicy.SOURCE)
+public @interface AllowUnusedImport {
+  /**
+   * The list of classes to suppress import warnings for.
+   */
+  Class<?>[] value();
+}
diff --git a/src/com/google/java/contract/ContractAssertionError.java b/src/com/google/java/contract/ContractAssertionError.java
new file mode 100644
index 0000000..6e87bd5
--- /dev/null
+++ b/src/com/google/java/contract/ContractAssertionError.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class for contract assertion errors. You should generally not
+ * catch this.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public abstract class ContractAssertionError extends AssertionError {
+  /**
+   * Constructs a new ContractAssertionError.
+   *
+   * @param msg the error message.
+   */
+  public ContractAssertionError(String msg) {
+    super(msg);
+    cleanStackTrace();
+  }
+
+  /**
+   * Constructs a new ContractAssertionError.
+   *
+   * @param msg the error message.
+   * @param throwable the throwable caught while evaluating contracts, or null
+   *        for none.
+   */
+  public ContractAssertionError(String msg, Throwable throwable) {
+    this(
+        throwable == null
+            ? msg
+            : "evaluating \"" + msg + "\" caused " + throwable.getClass().getSimpleName());
+  }
+
+  /**
+   * Constructs a new ContractAssertionError.
+   *
+   * @param msg the error message.
+   * @param cause a previous contract error
+   */
+  public ContractAssertionError(String msg, ContractAssertionError cause) {
+    super(msg);
+    initCause(cause);
+    cleanStackTrace();
+  }
+
+  /**
+   * Constructs a new ContractAssertionError.
+   *
+   * @param msg the error message.
+   * @param cause a previous contract error
+   * @param throwable the throwable caught while evaluating contracts, or null
+   *        for none.
+   */
+  public ContractAssertionError(String msg, ContractAssertionError cause, Throwable throwable) {
+    this(
+        throwable == null
+            ? msg
+            : "evaluating \"" + msg + "\" caused " + throwable.getClass().getSimpleName(),
+        cause);
+  }
+
+  /**
+   * Remove wrapper call, leaving only the contract helper.
+   */
+  private void cleanStackTrace() {
+    StackTraceElement[] realTrace = getStackTrace();
+    StackTraceElement[] trace = new StackTraceElement[realTrace.length - 1];
+    StackTraceElement top = realTrace[0];
+    trace[0] = new StackTraceElement(top.getClassName(),
+        getMethodName(realTrace[2].getMethodName()),
+        top.getFileName(), top.getLineNumber());
+    System.arraycopy(realTrace, 2, trace, 1, realTrace.length - 2);
+    setStackTrace(trace);
+  }
+
+  public List<String> getMessages() {
+    ArrayList<String> list = new ArrayList<String>();
+    Throwable error = this;
+    do {
+      list.add(error.getMessage());
+      error = error.getCause();
+    } while (error != null);
+    return list;
+  }
+
+  /**
+   * Returns the method name to show in the stack trace instead of the
+   * generated method name for the contract.
+   */
+  protected abstract String getMethodName(String contractedName);
+}
diff --git a/src/com/google/java/contract/ContractEnvironment.java b/src/com/google/java/contract/ContractEnvironment.java
new file mode 100644
index 0000000..bca925f
--- /dev/null
+++ b/src/com/google/java/contract/ContractEnvironment.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+/**
+ * An object that exposes methods to alter the contracting
+ * environment. Any changes made to the environment are only
+ * guaranteed to take effect on future actions; for example, disabling
+ * contracts on an already loaded class has no effect.
+ *
+ * <p>Methods that match multiple classes accept patterns. Patterns
+ * are semi-qualified names (nested classes have their names
+ * flattened), optionally followed by {@code .*}. A normal pattern
+ * matches itself exactly. A star pattern matches any class whose name
+ * begins with the pattern minus the terminating {@code .*}. In case
+ * of pattern overlap, subsequent rules override previous ones.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public interface ContractEnvironment {
+  /**
+   * Enables precondition checking for classes matched by pattern
+   * {@code pattern}.
+   *
+   * @throws UnsupportedOperationException if this environment does
+   * not support selective contract activation
+   */
+  @Requires("pattern != null")
+  @Ensures("hasPreconditionsEnabled(pattern)")
+  public void enablePreconditions(String pattern);
+
+  /**
+   * Disables precondition checking for classes matched by pattern
+   * {@code pattern}.
+   *
+   * @throws UnsupportedOperationException if this environment does
+   * not support selective contract activation
+   */
+  @Requires("pattern != null")
+  @Ensures("!hasPreconditionsEnabled(pattern)")
+  public void disablePreconditions(String pattern);
+
+  /**
+   * Enables postcondition checking for classes matched by pattern
+   * {@code pattern}.
+   *
+   * @throws UnsupportedOperationException if this environment does
+   * not support selective contract activation
+   */
+  @Requires("pattern != null")
+  @Ensures("hasPostconditionsEnabled(pattern)")
+  public void enablePostconditions(String pattern);
+
+  /**
+   * Disables postcondition checking for classes matched by pattern
+   * {@code pattern}.
+   *
+   * @throws UnsupportedOperationException if this environment does
+   * not support selective contract activation
+   */
+  @Requires("pattern != null")
+  @Ensures("!hasPostconditionsEnabled(pattern)")
+  public void disablePostconditions(String pattern);
+
+  /**
+   * Enables invariant checking for classes matched by pattern
+   * {@code pattern}.
+   *
+   * @throws UnsupportedOperationException if this environment does
+   * not support selective contract activation
+   */
+  @Requires("pattern != null")
+  @Ensures("hasInvariantsEnabled(pattern)")
+  public void enableInvariants(String pattern);
+
+  /**
+   * Disables invariant checking for classes matched by pattern
+   * {@code pattern}.
+   *
+   * @throws UnsupportedOperationException if this environment does
+   * not support selective contract activation
+   */
+  @Requires("pattern != null")
+  @Ensures("!hasInvariantsEnabled(pattern)")
+  public void disableInvariants(String pattern);
+
+  /**
+   * Returns {@code true} if {@code clazz} has preconditions
+   * enabled. This does <em>not</em> imply that such a class has any
+   * preconditions at all.
+   */
+  @Requires("clazz != null")
+  public boolean hasPreconditionsEnabled(Class<?> clazz);
+
+  /**
+   * Returns {@code true} if all classes matched by {@code pattern}
+   * have preconditions enabled. This does <em>not</em> imply that
+   * such a class has any preconditions at all.
+   */
+  @Requires("pattern != null")
+  public boolean hasPreconditionsEnabled(String pattern);
+
+  /**
+   * Returns {@code true} if {@code clazz} has postconditions
+   * enabled. This does <em>not</em> imply that such a class has any
+   * postconditions at all.
+   */
+  @Requires("clazz != null")
+  public boolean hasPostconditionsEnabled(Class<?> clazz);
+
+  /**
+   * Returns {@code true} if all classes matched by {@code pattern}
+   * have postconditions enabled. This does <em>not</em> imply that
+   * such a class has any postconditions at all.
+   */
+  @Requires("pattern != null")
+  public boolean hasPostconditionsEnabled(String pattern);
+
+  /**
+   * Returns {@code true} if {@code clazz} has invariants
+   * enabled. This does <em>not</em> imply that such a class has any
+   * invariants at all.
+   */
+  @Requires("clazz != null")
+  public boolean hasInvariantsEnabled(Class<?> clazz);
+
+  /**
+   * Returns {@code true} if all classes matched by {@code pattern}
+   * have invariants enabled. This does <em>not</em> imply that such a
+   * class has any invariants at all.
+   */
+  @Requires("pattern != null")
+  public boolean hasInvariantsEnabled(String pattern);
+
+  /**
+   * Ignores classes matched by {@code pattern}. Ignored classes are
+   * not touched by Contracts for Java in any way: they are neither
+   * loaded nor examined for contracts.
+   *
+   * <p>If you are looking for a method to disable contracts, this is
+   * <em>not</em> the right method; use methods such as
+   * {@link #disableInvariants(String)} instead.
+   *
+   * <p>By default, the following classes are ignored:
+   *
+   * <ul>
+   * <li>{@code java.*}
+   * <li>{@code javax.*}
+   * <li>{@code com.sun.*}
+   * <li>{@code sun.*}
+   * </ul>
+   */
+  @Requires("pattern != null")
+  @Ensures("isIgnored(pattern)")
+  public void ignore(String pattern);
+
+  /**
+   * Unignore classes matched by {@code pattern}. This method can be
+   * used to unignore some classes that have previously been ignored,
+   * or that are ignored by default.
+   *
+   * @see #ignore(String)
+   */
+  @Requires("pattern != null")
+  @Ensures("!isIgnored(pattern)")
+  public void unignore(String pattern);
+
+  /**
+   * Returns {@code true} if all classes matched by {@code pattern}
+   * are ignored.
+   *
+   * @see #ignore(String)
+   */
+  @Requires("pattern != null")
+  public boolean isIgnored(String pattern);
+}
diff --git a/src/com/google/java/contract/ContractEnvironmentConfigurator.java b/src/com/google/java/contract/ContractEnvironmentConfigurator.java
new file mode 100644
index 0000000..b4137da
--- /dev/null
+++ b/src/com/google/java/contract/ContractEnvironmentConfigurator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+/**
+ * An object that can be called by Contracts for Java to configure the
+ * contract environment.
+ *
+ * <p>As the last step of its startup procedure, Contracts for Java
+ * instantiates a new object of the class specified by the system
+ * property {@code com.google.java.contract.configurator} and calls the method
+ * {@link #configure(ContractEnvironment)} on it.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public interface ContractEnvironmentConfigurator {
+  /**
+   * Configures the contract environment. It is safe for this method
+   * to store {@code contractEnv} for later use, if needed.
+   */
+  @Requires("contractEnv != null")
+  public void configure(ContractEnvironment contractEnv);
+}
diff --git a/src/com/google/java/contract/Ensures.java b/src/com/google/java/contract/Ensures.java
new file mode 100644
index 0000000..a704c58
--- /dev/null
+++ b/src/com/google/java/contract/Ensures.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies postconditions that apply to the annotated method. The
+ * annotated method must establish its postconditions if and only if
+ * the preconditions were satisfied.
+ *
+ * <p>When run time checking of contracts is enabled, postconditions
+ * are checked at method exit, when the method exits normally, of the
+ * and throw a {@link com.google.java.contract.PreconditionError} when they
+ * are violated. Postconditions are not checked when the method exits
+ * by throwing an exception.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @see ThrowEnsures
+ */
+ at Documented
+ at Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Ensures {
+  /**
+   * The list of postconditions that must be met by the annotated
+   * method, written as strings. The expressions must be valid Java
+   * code and can reference all things visible to the class, as well
+   * as the method's arguments. Since postconditions may need to refer
+   * to the old value of an expression and the value returned by the
+   * annotated method, the following extensions are allowed:
+   *
+   * <p>The keyword {@code result} refers to the value returned from
+   * the method, if any. It is an error to have a method parameter
+   * named {@code result}.
+   *
+   * <p>The {@code old(expression)} pseudo-method construct refers to
+   * the value of its argument before execution of the method.
+   * {@code expression} must be a balanced expression, with regard to
+   * parentheses. The {@code old()} construct is preprocessed using
+   * the following simple rules (similar to macro expansion done by a
+   * C preprocessor):
+   *
+   * <ul>
+   * <li>the word {@code old}, followed by an opening parenthesis, is
+   * recognized as an identifier;
+   * <li>the enclosed expression is only parsed for balanced
+   * parentheses;
+   * <li>textual substitution is used.
+   * </ul>
+   *
+   * <p>It is an error to call a method named {@code old} from within
+   * a postcondition.
+   */
+  String[] value();
+}
diff --git a/src/com/google/java/contract/Invariant.java b/src/com/google/java/contract/Invariant.java
new file mode 100644
index 0000000..68e17f0
--- /dev/null
+++ b/src/com/google/java/contract/Invariant.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies class invariants that apply to the annotated type. The
+ * annotated class must guarantee its invariants.
+ *
+ * <p>When run time checking of contracts is enabled, class invariants
+ * are checked on entry and exit of public and package-private
+ * methods, and throw a {@link com.google.java.contract.InvariantError} when
+ * they are violated.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Documented
+ at Target(ElementType.TYPE)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Invariant {
+  /**
+   * The list of invariant expressions that must be met by the
+   * annotated type, written as strings. The expressions must be valid
+   * Java code and can reference all things visible to the class,
+   * including private members.
+   */
+  String[] value();
+}
diff --git a/src/com/google/java/contract/InvariantError.java b/src/com/google/java/contract/InvariantError.java
new file mode 100644
index 0000000..041715d
--- /dev/null
+++ b/src/com/google/java/contract/InvariantError.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+/**
+ * An exception thrown when a class invariant is violated.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ * @see com.google.java.contract.Invariant
+ */
+public class InvariantError extends ContractAssertionError {
+  /**
+   * Constructs a new InvariantError.
+   *
+   * @param msg the error message.
+   */
+  public InvariantError(String msg) {
+    super(msg, null);
+  }
+
+  /**
+   * Constructs a new InvariantError.
+   *
+   * @param msg the error message.
+   * @param throwable the throwable caught while evaluating contracts, or null
+   *        for none.
+   */
+  public InvariantError(String msg, Throwable throwable) {
+    super(msg, throwable);
+  }
+
+  @Override
+  protected String getMethodName(String contractedName) {
+    return "<invariant>";
+  }
+}
diff --git a/src/com/google/java/contract/PostconditionError.java b/src/com/google/java/contract/PostconditionError.java
new file mode 100644
index 0000000..4016c97
--- /dev/null
+++ b/src/com/google/java/contract/PostconditionError.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+/**
+ * An exception thrown when a postcondition is violated.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ * @see com.google.java.contract.Ensures
+ */
+public class PostconditionError extends ContractAssertionError {
+  /**
+   * Constructs a new PostconditionError.
+   *
+   * @param msg the error message.
+   */
+  public PostconditionError(String msg) {
+    super(msg, null);
+  }
+
+  /**
+   * Constructs a new PostconditionError.
+   *
+   * @param msg the error message.
+   * @param throwable the throwable caught while evaluating contracts, or null
+   *        for none.
+   */
+  public PostconditionError(String msg, Throwable throwable) {
+    super(msg, throwable);
+  }
+
+  @Override
+  protected String getMethodName(String contractedName) {
+    return contractedName + ".<post>";
+  }
+}
diff --git a/src/com/google/java/contract/PreconditionError.java b/src/com/google/java/contract/PreconditionError.java
new file mode 100644
index 0000000..b326113
--- /dev/null
+++ b/src/com/google/java/contract/PreconditionError.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+/**
+ * An exception thrown when a precondition is violated.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ * @see com.google.java.contract.Requires
+ */
+public class PreconditionError extends ContractAssertionError {
+  /**
+   * Constructs a new PreconditionError.
+   *
+   * @param msg the error message.
+   * @param cause a previously failing precondition
+   */
+  public PreconditionError(String msg, PreconditionError cause) {
+    super(msg, cause, null);
+  }
+
+  /**
+   * Constructs a new PreconditionError.
+   *
+   * @param msg the error message.
+   * @param cause a previously failing precondition
+   * @param throwable the throwable caught while evaluating contracts, or null
+   *        for none.
+   */
+  public PreconditionError(String msg, PreconditionError cause, Throwable throwable) {
+    super(msg, cause, throwable);
+  }
+
+  @Override
+  protected String getMethodName(String contractedName) {
+    return contractedName + ".<pre>";
+  }
+}
diff --git a/src/com/google/java/contract/Requires.java b/src/com/google/java/contract/Requires.java
new file mode 100644
index 0000000..11626e9
--- /dev/null
+++ b/src/com/google/java/contract/Requires.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies preconditions that apply to the annotated method. Callers
+ * must establish the preconditions of methods they call.
+ *
+ * <p>When run time checking of contracts is enabled, preconditions
+ * are checked at method entry and throw a
+ * {@link com.google.java.contract.PreconditionError} when they are violated.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Documented
+ at Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Requires {
+  /**
+   * The list of precondition expressions that must be met by the
+   * annotated method, written as strings. The expressions must be
+   * valid Java code and can reference all things visible to every
+   * caller of the method, as well as the method's arguments.
+   *
+   * <p>Expressions may also reference things that are not visible
+   * to the caller, such as private fields when the method is public,
+   * but this is considered bad style.
+   */
+  String[] value();
+}
diff --git a/src/com/google/java/contract/SpecificationError.java b/src/com/google/java/contract/SpecificationError.java
new file mode 100644
index 0000000..f8c347a
--- /dev/null
+++ b/src/com/google/java/contract/SpecificationError.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+/**
+ * An error in contract annotation usage.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class SpecificationError extends Error {
+  /**
+   * Constructs a new SpecificationError.
+   *
+   * @param msg the error message.
+   */
+  @Ensures("msg == null || msg.equals(getMessage())")
+  public SpecificationError(String msg) {
+    super(msg);
+  }
+}
diff --git a/src/com/google/java/contract/ThrowEnsures.java b/src/com/google/java/contract/ThrowEnsures.java
new file mode 100644
index 0000000..6166f6f
--- /dev/null
+++ b/src/com/google/java/contract/ThrowEnsures.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies exceptional postconditions that apply to the annotated
+ * method. Exceptional postconditions apply whenever the annotated
+ * method exits by throwing an exception, in contrast to normal
+ * postconditions that apply when the method exits normally. The
+ * annotated method must establish its postconditions if and only if
+ * the preconditions were satisfied.
+ *
+ * <p>When run time checking of contracts is enabled, exceptional
+ * postconditions are checked at method exit, when the method exits by
+ * throwing an exception, and throw a
+ * {@link com.google.java.contract.PostconditionError} when they are violated.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @see Ensures
+ */
+ at Documented
+ at Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface ThrowEnsures {
+  /**
+   * The alternating list of signal--postcondition pairs that must be
+   * met on throw. The expressions must be valid Java code and can
+   * reference all things visible to the class, as well as the
+   * method's arguments. Since exceptional postconditions may need to
+   * refer to the old value of an expression and the exception object
+   * thrown by the annotated method, the following extensions are
+   * allowed:
+   *
+   * <p>The {@code signal} keyword refers to the object thrown
+   * by the method, and has for static type
+   * {@link java.lang.Throwable}.
+   *
+   * <p>The {@code old()} construct has the same syntax and semantics
+   * as in normal postconditions.
+   *
+   * @see Ensures#value()
+   */
+  String[] value();
+}
diff --git a/src/com/google/java/contract/core/agent/ActivationRuleManager.java b/src/com/google/java/contract/core/agent/ActivationRuleManager.java
new file mode 100644
index 0000000..0c6f23b
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ActivationRuleManager.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.DebugUtils;
+import com.google.java.contract.core.util.PatternMap;
+
+/**
+ * A process-wide collection of contract activation rules.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "assertPre != null",
+  "assertPost != null",
+  "assertInvariant != null"
+})
+public class ActivationRuleManager {
+  protected static ActivationRuleManager instance = null;
+
+  protected PatternMap<Boolean> assertPre = new PatternMap<Boolean>();
+  protected PatternMap<Boolean> assertPost = new PatternMap<Boolean>();
+  protected PatternMap<Boolean> assertInvariant = new PatternMap<Boolean>();
+
+  protected ActivationRuleManager() {
+    assertPre = new PatternMap<Boolean>();
+    assertPost = new PatternMap<Boolean>();
+    assertInvariant = new PatternMap<Boolean>();
+  }
+
+  public static ActivationRuleManager getInstance() {
+    if (instance == null) {
+      instance = new ActivationRuleManager();
+    }
+    return instance;
+  }
+
+  @Requires("pattern != null")
+  @Ensures("hasPreconditionsEnabled(pattern)")
+  public synchronized void enablePreconditions(String pattern) {
+    DebugUtils.info("activation", pattern + " +requires");
+    assertPre.put(pattern, true);
+  }
+
+  @Requires("pattern != null")
+  @Ensures("!hasPreconditionsEnabled(pattern)")
+  public synchronized void disablePreconditions(String pattern) {
+    DebugUtils.info("activation", pattern + " -requires");
+    assertPre.put(pattern, false);
+  }
+
+  @Requires("pattern != null")
+  @Ensures("hasPostconditionsEnabled(pattern)")
+  public synchronized void enablePostconditions(String pattern) {
+    DebugUtils.info("activation", pattern + " +ensures");
+    assertPost.put(pattern, true);
+  }
+
+  @Requires("pattern != null")
+  @Ensures("!hasPostconditionsEnabled(pattern)")
+  public synchronized void disablePostconditions(String pattern) {
+    DebugUtils.info("activation", pattern + " -ensures");
+    assertPost.put(pattern, false);
+  }
+
+  @Requires("pattern != null")
+  @Ensures("hasInvariantsEnabled(pattern)")
+  public synchronized void enableInvariants(String pattern) {
+    DebugUtils.info("activation", pattern + " +invariant");
+    assertInvariant.put(pattern, true);
+  }
+
+  @Requires("pattern != null")
+  @Ensures("!hasInvariantsEnabled(pattern)")
+  public synchronized void disableInvariants(String pattern) {
+    DebugUtils.info("activation", pattern + " -invariant");
+    assertInvariant.put(pattern, false);
+  }
+
+  @Requires("pattern != null")
+  public synchronized boolean hasPreconditionsEnabled(String pattern) {
+    if (pattern.endsWith(".*") && assertPre.isOverriden(pattern)) {
+      return false;
+    }
+    Boolean rule = assertPre.get(pattern);
+    return rule == null || rule;
+  }
+
+  @Requires("pattern != null")
+  public synchronized boolean hasPostconditionsEnabled(String pattern) {
+    if (pattern.endsWith(".*") && assertPost.isOverriden(pattern)) {
+      return false;
+    }
+    Boolean rule = assertPost.get(pattern);
+    return rule == null || rule;
+  }
+
+  @Requires("pattern != null")
+  public synchronized boolean hasInvariantsEnabled(String pattern) {
+    if (pattern.endsWith(".*") && assertInvariant.isOverriden(pattern)) {
+      return false;
+    }
+    Boolean rule = assertInvariant.get(pattern);
+    return rule == null || rule;
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/AgentContractEnvironment.java b/src/com/google/java/contract/core/agent/AgentContractEnvironment.java
new file mode 100644
index 0000000..5b94b52
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/AgentContractEnvironment.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.core.runtime.RuntimeContractEnvironment;
+
+/**
+ * A contract environment running under the Cofoja Java agent.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("activationManager != null")
+public class AgentContractEnvironment extends RuntimeContractEnvironment {
+  protected ActivationRuleManager activationManager;
+
+  public AgentContractEnvironment() {
+    activationManager = ActivationRuleManager.getInstance();
+  }
+
+  @Override
+  public void enablePreconditions(String pattern) {
+    activationManager.enablePreconditions(pattern);
+  }
+
+  @Override
+  public void disablePreconditions(String pattern) {
+    activationManager.disablePreconditions(pattern);
+  }
+
+  @Override
+  public void enablePostconditions(String pattern) {
+    activationManager.enablePostconditions(pattern);
+  }
+
+  @Override
+  public void disablePostconditions(String pattern) {
+    activationManager.disablePostconditions(pattern);
+  }
+
+  @Override
+  public void enableInvariants(String pattern) {
+    activationManager.enableInvariants(pattern);
+  }
+
+  @Override
+  public void disableInvariants(String pattern) {
+    activationManager.disableInvariants(pattern);
+  }
+
+  @Override
+  public boolean hasPreconditionsEnabled(Class<?> clazz) {
+    return activationManager.hasPreconditionsEnabled(clazz.getName());
+  }
+
+  @Override
+  public boolean hasPreconditionsEnabled(String pattern) {
+    return activationManager.hasPreconditionsEnabled(pattern);
+  }
+
+  @Override
+  public boolean hasPostconditionsEnabled(Class<?> clazz) {
+    return activationManager.hasPostconditionsEnabled(clazz.getName());
+  }
+
+  @Override
+  public boolean hasPostconditionsEnabled(String pattern) {
+    return activationManager.hasPostconditionsEnabled(pattern);
+  }
+
+  @Override
+  public boolean hasInvariantsEnabled(Class<?> clazz) {
+    return activationManager.hasInvariantsEnabled(clazz.getName());
+  }
+
+  @Override
+  public boolean hasInvariantsEnabled(String pattern) {
+    return activationManager.hasInvariantsEnabled(pattern);
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/ClassContractHandle.java b/src/com/google/java/contract/core/agent/ClassContractHandle.java
new file mode 100644
index 0000000..212f8d6
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ClassContractHandle.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractKind;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.List;
+
+/**
+ * A contract handle representing a contract method with class-wide
+ * effect.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class ClassContractHandle extends ContractHandle {
+  /**
+   * Constructs a new ClassContractHandle.
+   *
+   * @param kind the kind of this ClassContractHandle
+   * @param className the class this handle belongs to
+   * @param contractMethod the {@link MethodNode} representing this
+   * handle's method
+   * @param lineNumbers the line numbers associated with the contract
+   */
+  @Requires({
+    "kind != null",
+    "className != null",
+    "contractMethod != null"
+  })
+  @Ensures({
+    "kind == getKind()",
+    "className.equals(getClassName())",
+    "contractMethod == getContractMethod()",
+    "lineNumbers == getLineNumbers()"
+  })
+  public ClassContractHandle(ContractKind kind, String className,
+                             MethodNode contractMethod,
+                             List<Long> lineNumbers) {
+    super(kind, className, contractMethod, lineNumbers);
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/ContractAnalyzer.java b/src/com/google/java/contract/core/agent/ContractAnalyzer.java
new file mode 100644
index 0000000..931dbe3
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ContractAnalyzer.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Bytecode class visitor responsible for contract information
+ * extraction.
+ *
+ * After a class has been visited, this visitor exposes the resulting
+ * handles through filtering accessor methods such as
+ * {@link #getClassHandles(ContractKind)}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+ at AllowUnusedImport({ ClassName.class, Iterables.class, Predicates.class })
+ at Invariant({
+  "className == null || ClassName.isBinaryName(className)",
+  "classHandles != null",
+  "!classHandles.contains(null)",
+  "methodHandles != null",
+  "!methodHandles.keySet().contains(null)",
+  "Iterables.all(methodHandles.values(), " +
+      "Predicates.<MethodContractHandle>all(Predicates.nonNull()))"
+})
+class ContractAnalyzer extends ClassVisitor {
+  protected List<ClassContractHandle> classHandles;
+  protected Map<String, ArrayList<MethodContractHandle>> methodHandles;
+
+  protected String className;
+  protected MethodNode lastMethodNode;
+
+  /**
+   * Constructs an empty ContractAnalyzer. The ContractAnalyzer is
+   * intended to be filled through its visitor interface.
+   */
+  ContractAnalyzer() {
+    super(Opcodes.ASM4);
+    classHandles = new ArrayList<ClassContractHandle>();
+    methodHandles = new HashMap<String, ArrayList<MethodContractHandle>>();
+  }
+
+  /**
+   * Returns the ClassHandle objects matching the specified criteria.
+   *
+   * @param kind the kind of the handles
+   * @return a list containing the requested handles
+   */
+  @Requires("kind != null")
+  @Ensures({
+    "result != null",
+    "!result.contains(null)"
+  })
+  List<ClassContractHandle> getClassHandles(ContractKind kind) {
+    ArrayList<ClassContractHandle> matched =
+        new ArrayList<ClassContractHandle>();
+    for (ClassContractHandle h : classHandles) {
+      if (kind.equals(h.getKind())) {
+        matched.add(h);
+      }
+    }
+    return matched;
+  }
+
+  /**
+   * Returns the MethodHandle objects matching the specified criteria.
+   *
+   * @param kind the kind of the handles
+   * @param name the target method name
+   * @param desc the target method descriptor
+   * @param extraCount the number of extra parameters in the contract
+   * method
+   * @return a list containing the requested handles
+   */
+  @Requires({
+    "kind != null",
+    "name != null",
+    "desc != null",
+    "extraCount >= 0"
+  })
+  @Ensures({
+    "result != null",
+    "!result.contains(null)"
+  })
+  List<MethodContractHandle> getMethodHandles(ContractKind kind,
+      String name, String desc, int extraCount) {
+    ArrayList<MethodContractHandle> candidates = methodHandles.get(name);
+    if (candidates == null) {
+      return Collections.emptyList();
+    }
+
+    ArrayList<MethodContractHandle> matched =
+        new ArrayList<MethodContractHandle>();
+    for (MethodContractHandle h : candidates) {
+      if (kind.equals(h.getKind())
+          && descArgumentsMatch(desc, h.getContractMethod().desc, extraCount)) {
+        matched.add(h);
+      }
+    }
+    return matched;
+  }
+
+  /**
+   * Returns the first ClassHandle object matching the specified
+   * criteria.
+   *
+   * @param kind the kind of the handle
+   * @return a handle matching the criteria, or {@code null}
+   */
+  @Requires("kind != null")
+  ClassContractHandle getClassHandle(ContractKind kind) {
+    ArrayList<ClassContractHandle> matched =
+        new ArrayList<ClassContractHandle>();
+    for (ClassContractHandle h : classHandles) {
+      if (kind.equals(h.getKind())) {
+        return h;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns the first MethodHandle object matching the specified
+   * criteria.
+   *
+   * @param kind the kind of the handle
+   * @param name the target method name
+   * @param desc the target method descriptor
+   * @param extraCount the number of extra parameters in the contract
+   * method
+   * @return a handle matching the criteria, or {@code null}
+   */
+  @Requires({
+    "kind != null",
+    "name != null",
+    "desc != null",
+    "extraCount >= 0"
+  })
+  MethodContractHandle getMethodHandle(ContractKind kind,
+      String name, String desc, int extraCount) {
+    ArrayList<MethodContractHandle> candidates = methodHandles.get(name);
+    if (candidates == null) {
+      return null;
+    }
+
+    for (MethodContractHandle h : candidates) {
+      if (kind.equals(h.getKind())
+          && descArgumentsMatch(desc, h.getContractMethod().desc, extraCount)) {
+        return h;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns {@code true} if the argument descriptors {@code desc1}
+   * and {@code desc2} are equal (return type is ignored), ignoring
+   * the last {@code offset} parameters of {@code desc2}.
+   */
+  @Requires({
+    "desc1 != null",
+    "desc2 != null",
+    "offset >= 0"
+  })
+  private boolean descArgumentsMatch(String desc1, String desc2, int offset) {
+    Type[] types1 = Type.getArgumentTypes(desc1);
+    Type[] types2 = Type.getArgumentTypes(desc2);
+
+    if (types2.length - types1.length != offset) {
+      return false;
+    }
+    for (int i = 0; i < types1.length; ++i) {
+      if (!types1[i].equals(types2[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /*
+   * Visitor implementation.
+   */
+
+  @Override
+  public void visit(int version, int access,
+                    String name, String signature,
+                    String superName, String[] interfaceNames) {
+    className = name;
+  }
+
+  @Override
+  public MethodVisitor visitMethod(int access, String name, String desc,
+                                   String signature, String[] exceptions) {
+    captureLastMethodNode();
+    lastMethodNode = new MethodNode(access, name, desc, signature, exceptions);
+    return lastMethodNode;
+  }
+
+  @Override
+  public void visitEnd() {
+    captureLastMethodNode();
+  }
+
+  /**
+   * Creates a contract handle for the method last visited, if it was
+   * a contract method.
+   */
+  @Ensures("lastMethodNode == null")
+  protected void captureLastMethodNode() {
+    if (lastMethodNode == null) {
+      return;
+    }
+
+    ContractKind kind = ContractMethodSignatures.getKind(lastMethodNode);
+    if (kind != null) {
+      List<Long> lineNumbers =
+          ContractMethodSignatures.getLineNumbers(lastMethodNode);
+
+      if (kind.isClassContract() || kind.isHelperContract()) {
+        ClassContractHandle ch =
+            new ClassContractHandle(kind, className,
+                                    lastMethodNode, lineNumbers);
+        classHandles.add(ch);
+      } else {
+        MethodContractHandle mh =
+            new MethodContractHandle(kind, className,
+                                     lastMethodNode, lineNumbers);
+        internMethod(mh.getMethodName()).add(mh);
+      }
+    }
+
+    lastMethodNode = null;
+  }
+
+  /**
+   * Returns the contract handle collection corresponding to the
+   * method named {@code name}.
+   */
+  @Requires("name != null")
+  @Ensures({
+    "result != null",
+    "result == methodHandles.get(name)"
+  })
+  protected List<MethodContractHandle> internMethod(String name) {
+    ArrayList<MethodContractHandle> handles = methodHandles.get(name);
+    if (handles == null) {
+      handles = new ArrayList<MethodContractHandle>();
+      methodHandles.put(name, handles);
+    }
+    return handles;
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/ContractClassFileTransformer.java b/src/com/google/java/contract/core/agent/ContractClassFileTransformer.java
new file mode 100644
index 0000000..e75bcc3
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ContractClassFileTransformer.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.runtime.BlacklistManager;
+import com.google.java.contract.core.util.DebugUtils;
+import com.google.java.contract.core.util.JavaUtils;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * A class transformer responsible for instrumenting classes with
+ * contracts. Only classes that have contracts will be instrumented.
+ *
+ * <p>The transformation process works in two steps:
+ *
+ * <ol>
+ * <li>The contract methods are extracted recursively from the
+ * contract class files and stored in the {@link ContractCodePool}.
+ * <li>Each individual class is instrumented with its contracts, taken
+ * from the pool.
+ * </ol>
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+ at AllowUnusedImport(ClassName.class)
+public class ContractClassFileTransformer implements ClassFileTransformer {
+  /**
+   * Find and store superclass information.
+   */
+  private class SuperInfoFinder extends ClassVisitor {
+    private SuperInfoFinder() {
+      super(Opcodes.ASM4);
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature,
+                      String superName, String[] interfaces) {
+      super.visit(version, access, name, signature, superName, interfaces);
+
+      HashSet<String> assignable = new HashSet<String>();
+      assignable.add(name);
+      assignableToNames.put(name, assignable);
+
+      if (superName != null) {
+        superClassNames.put(name, superName);
+        assignable.add(superName);
+        findSuperInfo(superName);
+        assignable.addAll(assignableToNames.get(superName));
+      }
+
+      for (String ifaceName : interfaces) {
+        assignable.add(ifaceName);
+        findSuperInfo(ifaceName);
+        assignable.addAll(assignableToNames.get(ifaceName));
+      }
+    }
+
+    /**
+     * Look up information about super classes and assignable types
+     * for the class named {@code className}.
+     */
+    @Requires("ClassName.isBinaryName(className)")
+    private void findSuperInfo(String className) {
+      if (superClassNames.containsKey(className)) {
+        return;
+      }
+      if (blacklistManager.isIgnored(new ClassName(className)
+                                     .getQualifiedName())) {
+        findSuperInfoFromClass(className);
+      } else {
+        findSuperInfoFromClassFile(className);
+      }
+    }
+
+    @Requires("ClassName.isBinaryName(className)")
+    private void findSuperInfoFromClassFile(String className) {
+      try {
+        InputStream stream = JavaUtils.getClassInputStream(loader, className);
+        if (stream == null)
+          throw new NullPointerException();
+        ClassReader reader = new ClassReader(stream);
+        reader.accept(this, 0);
+      } catch (Exception e) {
+        addDefaultAssignable(className);
+      }
+    }
+
+    @Requires("ClassName.isBinaryName(className)")
+    private void findSuperInfoFromClass(String className) {
+      Class<?> clazz;
+      try {
+        String qName = new ClassName(className).getQualifiedName();
+        clazz = Class.forName(qName, false, loader);
+      } catch (ClassNotFoundException e) {
+        addDefaultAssignable(className);
+        return;
+      }
+
+      Class<?> superClass = clazz.getSuperclass();
+      if (superClass == null) {
+        addDefaultAssignable(className);
+        return;
+      }
+
+      HashSet<String> assignable = new HashSet<String>();
+      assignable.add(className);
+      assignableToNames.put(className, assignable);
+
+      String superName = superClass.getName().replace('.', '/');
+      superClassNames.put(className, superName);
+      assignable.add(superName);
+      findSuperInfo(superName);
+      assignable.addAll(assignableToNames.get(superName));
+
+      for (Class<?> iface : clazz.getInterfaces()) {
+        String ifaceName = iface.getName().replace('.', '/');
+        assignable.add(ifaceName);
+        findSuperInfo(ifaceName);
+        assignable.addAll(assignableToNames.get(ifaceName));
+      }
+    }
+
+    /**
+     * Add default super type information for the class named
+     * {@code className}. The default information makes the class
+     * a direct child of Object and assignable to it (and to itself)
+     * as well.
+     */
+    @Requires("className != null")
+    private void addDefaultAssignable(String className) {
+      if (!superClassNames.containsKey(className)) {
+        superClassNames.put(className, "java/lang/Object");
+      }
+      HashSet<String> assignable = new HashSet<String>();
+      assignable.add(className);
+      assignable.add("java/lang/Object");
+      assignableToNames.put(className, assignable);
+    }
+  }
+
+  /**
+   * A ClassWriter that does not load new classes. Tries to get the
+   * information from class files; an exception is made for
+   * blacklisted classes, which <em>are</em> loaded as usual. There
+   * should be no conflict as blacklisted hierarchies should be
+   * distinct from contracted ones.
+   */
+  protected class NonLoadingClassWriter extends ClassWriter {
+    @Requires("reader != null")
+    public NonLoadingClassWriter(ClassReader reader, int flags) {
+      super(reader, flags);
+    }
+
+    /*
+     * TODO(lenh): IMPORTANT NOTE. Computing stack frames in a purely
+     * forward fashion (from definitions to uses) using this method
+     * cannot be correct in some cases, no matter how accurate the
+     * type we return here. If two supertypes are possible (e.g., two
+     * interfaces) and one of them is needed for a following call,
+     * there's a 1/2 chance to pick the wrong one since the use is
+     * unknown at the time of the merge definition. It is unclear to
+     * me what the expected semantics of this method are, or what
+     * analysis (forward or backward) is actually performed by ASM
+     * when computing frames. Also, as is the case with the official
+     * implementation, this method does not handle interfaces
+     * completely.
+     */
+    @Override
+    protected String getCommonSuperClass(String className1, String className2) {
+      if (className1.equals(className2)) {
+        return className1;
+      }
+      SuperInfoFinder superInfoFinder = new SuperInfoFinder();
+      superInfoFinder.findSuperInfo(className1);
+      superInfoFinder.findSuperInfo(className2);
+      if (assignableToNames.get(className1).contains(className2)) {
+        return className2;
+      }
+      while (!assignableToNames.get(className2).contains(className1)) {
+        className1 = superClassNames.get(className1);
+      }
+      return className1;
+    }
+  }
+
+  protected BlacklistManager blacklistManager;
+
+  protected ClassLoader loader;
+
+  /*
+   * TODO(lenh): Use a LinkedHashMap for the two following fields,
+   * with some caching mechanism.
+   */
+
+  protected Map<String, Set<String>> assignableToNames =
+      new HashMap<String, Set<String>>();
+
+  protected Map<String, String> superClassNames = new HashMap<String, String>();
+
+  /**
+   * Constructs a new ContractClassFileTransformer.
+   */
+  public ContractClassFileTransformer() {
+    blacklistManager = BlacklistManager.getInstance();
+  }
+
+  /**
+   * Constructs a new ContractClassFileTransformer with default class
+   * loader {@code loader}. Subsequently,
+   * {@link #instrumentWithContracts(byte[],ContractAnalyzer)} may be
+   * called directly and will use the default loader.
+   */
+  public ContractClassFileTransformer(ClassLoader loader) {
+    this();
+    this.loader = loader;
+  }
+
+  /**
+   * Instruments the specified class, if necessary.
+   */
+  @Override
+  public byte[] transform(ClassLoader loader, String className,
+      Class<?> redefinedClass, ProtectionDomain protectionDomain,
+      byte[] bytecode) {
+    if (blacklistManager.isIgnored(className)) {
+      DebugUtils.info("agent", "ignoring " + className);
+      return null;
+    }
+    try {
+      this.loader = loader;
+      ContractAnalyzer contracts = analyze(className);
+      if (contracts == null) {
+        if (className.endsWith(JavaUtils.HELPER_CLASS_SUFFIX)) {
+          DebugUtils.info("agent", "adding source info to " + className);
+          return instrumentWithDebug(bytecode);
+        } else {
+          return null;
+        }
+      } else {
+        DebugUtils.info("agent", "adding contracts to " + className);
+        return instrumentWithContracts(bytecode, contracts);
+      }
+    } catch (Throwable e) {
+      DebugUtils.err("agent", "while instrumenting " + className, e);
+      /* Not reached. */
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Instruments the specified class with contracts.
+   */
+  @Requires({
+    "bytecode != null",
+    "contractBytecode != null"
+  })
+  @Ensures("result != null")
+  public byte[] transformWithContracts(byte[] bytecode, byte[] contractBytecode)
+      throws IllegalClassFormatException {
+    try {
+      ContractAnalyzer contracts =
+          extractContracts(new ClassReader(contractBytecode));
+      return instrumentWithContracts(bytecode, contracts);
+    } catch (Throwable t) {
+      /* If the class file contains errors, ASM will just crash. */
+      IllegalClassFormatException e = new IllegalClassFormatException();
+      e.initCause(t);
+      throw e;
+    }
+  }
+
+  /**
+   * Instruments the specified class with debug information.
+   */
+  @Requires("bytecode != null")
+  @Ensures("result != null")
+  public byte[] transformWithDebug(byte[] bytecode)
+      throws IllegalClassFormatException {
+    try {
+      return instrumentWithDebug(bytecode);
+    } catch (Throwable t) {
+      /* If the class file contains errors, ASM will just crash. */
+      IllegalClassFormatException e = new IllegalClassFormatException();
+      e.initCause(t);
+      throw e;
+    }
+  }
+
+  /**
+   * Extracts contract methods for the specified class, if necessary.
+   *
+   * @param className the class name
+   * @return the extracted contracts or {@code null} if the class has
+   * none and should not be instrumented
+   */
+  @Requires("ClassName.isBinaryName(className)")
+  protected ContractAnalyzer analyze(String className)
+      throws IOException {
+    /* Skip helper classes. */
+    if (className.endsWith(JavaUtils.HELPER_CLASS_SUFFIX)) {
+      return null;
+    }
+
+    /* Skip interfaces. */
+    String helperFileName = className + JavaUtils.HELPER_CLASS_SUFFIX
+        + Kind.CLASS.extension;
+    if (JavaUtils.resourceExists(loader, helperFileName)) {
+      return null;
+    }
+
+    /* Try to get contracts class file. */
+    InputStream contractStream =
+        JavaUtils.getContractClassInputStream(loader, className);
+    if (contractStream == null) {
+      return null;
+    }
+
+    return extractContracts(new ClassReader(contractStream));
+  }
+
+  /**
+   * Processes the specified reader and returns extracted contracts.
+   */
+  @Requires("reader != null")
+  protected ContractAnalyzer extractContracts(ClassReader reader) {
+    ContractAnalyzer contractAnalyzer = new ContractAnalyzer();
+    reader.accept(contractAnalyzer, ClassReader.EXPAND_FRAMES);
+    return contractAnalyzer;
+  }
+
+  /**
+   * Instruments the passed class file so that it contains contract
+   * methods and calls to these methods. The contract information is
+   * retrieved from the {@link ContractCodePool}.
+   *
+   * @param bytecode the bytecode of the class
+   * @param contracts the extracted contracts for the class
+   * @return the instrumented bytecode of the class
+   */
+  @Requires({
+    "bytecode != null",
+    "contracts != null"
+  })
+  @Ensures("result != null")
+  protected byte[] instrumentWithContracts(byte[] bytecode,
+                                           ContractAnalyzer contracts) {
+    ClassReader reader = new ClassReader(bytecode);
+    ClassWriter writer =
+        new NonLoadingClassWriter(reader,
+                                  ClassWriter.COMPUTE_FRAMES |
+                                  ClassWriter.COMPUTE_MAXS);
+
+    SpecificationClassAdapter adapter =
+        new SpecificationClassAdapter(writer, contracts);
+    reader.accept(adapter, ClassReader.EXPAND_FRAMES);
+
+    return writer.toByteArray();
+  }
+
+  /**
+   * Instruments the passed class file so that it contains debug
+   * information extraction from annotations.
+   */
+  @Requires("bytecode != null")
+  @Ensures("result != null")
+  private byte[] instrumentWithDebug(byte[] bytecode) {
+    ClassReader reader = new ClassReader(bytecode);
+    ClassWriter writer = new NonLoadingClassWriter(reader, 0);
+    reader.accept(new HelperClassAdapter(writer), ClassReader.EXPAND_FRAMES);
+    return writer.toByteArray();
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/ContractFixingClassAdapter.java b/src/com/google/java/contract/core/agent/ContractFixingClassAdapter.java
new file mode 100644
index 0000000..038c3f6
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ContractFixingClassAdapter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.JavaUtils;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A class adapter that transforms injected contract methods to remove
+ * contract compilation artefacts:
+ *
+ * <ul>
+ * <li>fix calls to {@code access$n} synthetic methods for inner/nested
+ * classes.
+ * </ul>
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+class ContractFixingClassAdapter extends ClassVisitor {
+  /**
+   * A method adapter that amends calls to {@code access$n} synthetic
+   * methods. These methods are generated for access to members from
+   * inner/nested classes. Contract compilation may generate some of
+   * these, which are renamed and injected into the original class
+   * bytecode during instrumentation. Calls to these methods need to
+   * be fixed to use the new names.
+   */
+  protected static class AccessMethodAdapter extends MethodVisitor {
+    /**
+     * Constructs a new AccessMethodAdapter.
+     *
+     * @param mv the MethodVisitor this adapter delegates to
+     */
+    @Requires("mv != null")
+    public AccessMethodAdapter(MethodVisitor mv) {
+      super(Opcodes.ASM4, mv);
+    }
+
+    /**
+     * Converts calls to {@code access$n} synthetic methods to the
+     * equivalent injected methods.
+     */
+    @Override
+    public void visitMethodInsn(int opcode, String owner, String name,
+                                String desc) {
+      if (!name.startsWith("access$")) {
+        mv.visitMethodInsn(opcode, owner, name, desc);
+      } else {
+        mv.visitMethodInsn(opcode, owner,
+                           JavaUtils.SYNTHETIC_MEMBER_PREFIX + name, desc);
+      }
+    }
+  }
+
+  /**
+   * Constructs a new ContractFixingClassAdapter.
+   *
+   * @param cv the ClassVisitor this adapter delegates to
+   */
+  @Requires("cv != null")
+  public ContractFixingClassAdapter(ClassVisitor cv) {
+    super(Opcodes.ASM4, cv);
+  }
+
+  /**
+   * Visits the specified method fixing method calls.
+   */
+  @Override
+  public MethodVisitor visitMethod(int access, String name, String desc,
+                                   String signature, String[] exceptions) {
+    MethodVisitor mv = cv.visitMethod(access | Opcodes.ACC_SYNTHETIC,
+                                      name, desc, signature, exceptions);
+    return new AccessMethodAdapter(mv);
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/ContractHandle.java b/src/com/google/java/contract/core/agent/ContractHandle.java
new file mode 100644
index 0000000..c8e348b
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ContractHandle.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.core.util.JavaUtils;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.List;
+
+/**
+ * A handle representing a contract method at run time. The handle
+ * gives access to the contract method as well as metadata required
+ * to instrument the elements it targets.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+ at AllowUnusedImport({ ClassName.class, Iterables.class, Predicates.class })
+ at Invariant({
+  "getKind() != null",
+  "ClassName.isBinaryName(getClassName())",
+  "getKey() >= -1",
+  "getLineNumbers() == null " +
+      "|| ContractMethodSignatures.isLineNumberList(getLineNumbers())"
+})
+public class ContractHandle {
+  protected ContractKind kind;
+  protected String className;
+  protected int key;
+
+  protected MethodNode contractMethod;
+  protected List<Long> lineNumbers;
+
+  protected boolean injected;
+
+  /**
+   * Constructs a new ContractHandle.
+   *
+   * @param kind the kind of the contract handle
+   * @param className the name of the contracted class
+   * @param contractMethod the method node holding the actual
+   * implementation of the contract method
+   * @param lineNumbers the line numbers associated with the contract
+   */
+  @Requires({
+    "kind != null",
+    "ClassName.isBinaryName(className)",
+    "contractMethod != null",
+    "lineNumbers == null " +
+        "|| ContractMethodSignatures.isLineNumberList(lineNumbers)"
+  })
+  @Ensures({
+    "kind == getKind()",
+    "className.equals(getClassName())",
+    "contractMethod == getContractMethod()",
+    "lineNumbers == getLineNumbers()",
+    "!isInjected()"
+  })
+  protected ContractHandle(ContractKind kind, String className,
+                           MethodNode contractMethod, List<Long> lineNumbers) {
+    this.kind = kind;
+    this.className = className;
+    key = ContractMethodSignatures.getId(contractMethod);
+
+    this.contractMethod = contractMethod;
+    if (!contractMethod.name.startsWith("com$google$java$contract$")) {
+      contractMethod.name =
+          JavaUtils.SYNTHETIC_MEMBER_PREFIX + contractMethod.name;
+    }
+    this.lineNumbers = lineNumbers;
+
+    this.injected = false;
+  }
+
+  public ContractKind getKind() {
+    return kind;
+  }
+
+  public String getClassName() {
+    return className;
+  }
+
+  public int getKey() {
+    return key;
+  }
+
+  public MethodNode getContractMethod() {
+    return contractMethod;
+  }
+
+  public List<Long> getLineNumbers() {
+    return lineNumbers;
+  }
+
+  public boolean isInjected() {
+    return injected;
+  }
+
+  @Ensures("injected == isInjected()")
+  public void setInjected(boolean injected) {
+    this.injected = injected;
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/ContractMethodSignature.java b/src/com/google/java/contract/core/agent/ContractMethodSignature.java
new file mode 100644
index 0000000..0832d99
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ContractMethodSignature.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.core.model.ContractKind;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Meta data attached to a contract method. The metadata is generated
+ * at compile-time by the contract compiler and provides information
+ * to the runtime Java agent about the purpose of the contract
+ * method. No two contract methods in a same class should have the
+ * same signature.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.CLASS)
+public @interface ContractMethodSignature {
+  /**
+   * The kind of contract method, which determines its role with
+   * regard to the contracted class.
+   */
+  ContractKind kind();
+
+  /**
+   * The target of the contract method. Either the name of a method or
+   * the empty string if the contract targets the whole class.
+   */
+  String target() default "";
+
+  /**
+   * The ID of the contract method. IDs are used to distinguish
+   * between two contract methods with similar roles.
+   */
+  int id() default -1;
+
+  /**
+   * The line numbers where the original contract is located.
+   */
+  long[] lines() default {};
+}
diff --git a/src/com/google/java/contract/core/agent/ContractMethodSignatures.java b/src/com/google/java/contract/core/agent/ContractMethodSignatures.java
new file mode 100644
index 0000000..2378ac1
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/ContractMethodSignatures.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractKind;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Utility methods to read contract method signature components.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @see com.google.java.contract.core.agent.ContractMethodSignature
+ */
+class ContractMethodSignatures {
+  static final String CONTRACT_METHOD_SIGNATURE_DESC =
+      Type.getObjectType("com/google/java/contract/core/agent/ContractMethodSignature")
+      .getDescriptor();
+
+  @Requires("contractMethod != null")
+  static String getTarget(MethodNode contractMethod) {
+    return getMetaData(contractMethod, "target", String.class);
+  }
+
+  @Requires("contractMethod != null")
+  static ContractKind getKind(MethodNode contractMethod) {
+    String[] pair = getMetaData(contractMethod, "kind", String[].class);
+    if (pair != null) {
+      return Enum.valueOf(ContractKind.class, pair[1]);
+    } else if (contractMethod.name.startsWith("access$")) {
+      return ContractKind.ACCESS;
+    } else {
+      return null;
+    }
+  }
+
+  @Requires("contractMethod != null")
+  @Ensures("result >= -1")
+  static int getId(MethodNode contractMethod) {
+    Integer id = getMetaData(contractMethod, "id", Integer.class);
+    return id == null || id < 0 ? -1 : id;
+  }
+
+  @Requires("contractMethod != null")
+  @Ensures("result == null || isLineNumberList(result)")
+  static List<Long> getLineNumbers(MethodNode contractMethod) {
+    Object lines = getMetaData(contractMethod, "lines", Object.class);
+    return getLineNumbers(lines);
+  }
+
+  /**
+   * Converts either a {@code long[]} or {@code List<Long>} object as
+   * obtained by reading the annotation to a {@code List<Long>} with
+   * {@code null} instead of negative values to represent non-existent
+   * line information.
+   *
+   * TODO(lenh): ASM documentation states the returned annotation
+   * value should be a list but the library returns an array.
+   */
+  @SuppressWarnings("unchecked")
+  @Ensures({
+    "lines == null ? result == null : isLineNumberList(result)"
+  })
+  static List<Long> getLineNumbers(Object lines) {
+    if (lines == null) {
+      return null;
+    }
+
+    ArrayList<Long> lineNumbers = new ArrayList<Long>();
+    if (lines.getClass().isArray()) {
+      for (long line : (long[]) lines) {
+        lineNumbers.add(line < 1 ? null : line);
+      }
+    } else {
+      for (Long line : (List<Long>) lines) {
+        lineNumbers.add(line < 1 ? null : line);
+      }
+    }
+
+    return lineNumbers;
+  }
+
+  /**
+   * Returns {@code true} if {@code list} is a proper line number list
+   * as used by Contracts for Java in the bytecode instrumenter and
+   * associated components.
+   */
+  static boolean isLineNumberList(List<Long> list) {
+    if (list == null) {
+      return false;
+    }
+    for (Long line : list) {
+      if (line != null && line < 1) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Extracts the method signature field named {@code field}, with the
+   * type {@code clazz}, from the annotations of
+   * {@code contractMethod}.
+   *
+   * @param contractMethod the annotated method node
+   * @param field the name of the field to retrieve
+   * @param clazz the type of the value to return
+   * @return the value of the field, or {@code null}
+   */
+  @Requires({
+    "contractMethod != null",
+    "field != null",
+    "clazz != null"
+  })
+  @SuppressWarnings("unchecked")
+  static <T> T getMetaData(MethodNode contractMethod,
+                           String field, Class<T> clazz) {
+    List<AnnotationNode> annotations = contractMethod.invisibleAnnotations;
+    if (annotations == null) {
+      return null;
+    }
+
+    for (AnnotationNode annotation : annotations) {
+      if (!annotation.desc.equals(CONTRACT_METHOD_SIGNATURE_DESC)) {
+        continue;
+      }
+
+      if (annotation.values == null) {
+        return null;
+      }
+
+      Iterator<?> it = annotation.values.iterator();
+      while (it.hasNext()) {
+        String name = (String) it.next();
+        Object value = it.next();
+        if (name.equals(field)) {
+          return (T) value;
+        }
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/HelperClassAdapter.java b/src/com/google/java/contract/core/agent/HelperClassAdapter.java
new file mode 100644
index 0000000..e32a746
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/HelperClassAdapter.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.JavaUtils;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Adds debug information to a helper class.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+class HelperClassAdapter extends ClassVisitor {
+  protected class HelperMethodAdapter extends LineNumberingMethodAdapter {
+    /**
+     * Constructs a new HelperMethodAdapter.
+     *
+     * @param mv the MethodVisitor this adapter delegates to
+     * @param access the access flags of the method
+     * @param name the name of the method
+     * @param desc the descriptor of the method
+     */
+    @Requires({
+      "mv != null",
+      "name != null",
+      "desc != null"
+    })
+    public HelperMethodAdapter(MethodVisitor mv, int access,
+                               String name, String desc) {
+      super(mv, access, name, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+      if (Type.getType(desc).getInternalName().equals(
+              "com/google/java/contract/core/agent/ContractMethodSignature")) {
+        return new AnnotationVisitor(Opcodes.ASM4) {
+          @Override
+          public void visit(String name, Object value) {
+            if (name.equals("lines")) {
+              lineNumbers = ContractMethodSignatures.getLineNumbers(value);
+            }
+          }
+        };
+      }
+      return super.visitAnnotation(desc, visible);
+    }
+  }
+
+  @Requires("cv != null")
+  public HelperClassAdapter(ClassVisitor cv) {
+    super(Opcodes.ASM4, cv);
+  }
+
+  @Override
+  public void visitSource(String source, String debug) {
+    /*
+     * Work around bogus file names and remove helper suffix if
+     * found. The compiler, as invoked in ContractJavaCompiler,
+     * produces SourceFile entries with a trailing ']' for no apparent
+     * reason; this method removes any trailing characters after the
+     * source extension.
+     */
+    String name =
+        source.substring(0, source.lastIndexOf(Kind.SOURCE.extension));
+    if (name.endsWith(JavaUtils.HELPER_CLASS_SUFFIX)) {
+      int lengthSansSuffix =
+          name.length() - JavaUtils.HELPER_CLASS_SUFFIX.length();
+      name = name.substring(0, lengthSansSuffix);
+    }
+    name += Kind.SOURCE.extension;
+    cv.visitSource(name, debug);
+  }
+
+  @Override
+  public MethodVisitor visitMethod(int access, String name, String desc,
+                                   String signature, String[] exceptions) {
+    MethodVisitor mv =
+        cv.visitMethod(access, name, desc, signature, exceptions);
+    return new HelperMethodAdapter(mv, access, name, desc);
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/LineNumberingClassAdapter.java b/src/com/google/java/contract/core/agent/LineNumberingClassAdapter.java
new file mode 100644
index 0000000..60c81f0
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/LineNumberingClassAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+import java.util.List;
+
+/**
+ * A class adapter that adds a line number to methods.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("ContractMethodSignatures.isLineNumberList(lineNumbers)")
+class LineNumberingClassAdapter extends ClassVisitor {
+  protected List<Long> lineNumbers;
+
+  /**
+   * Constructs a new LineNumberingClassAdapter.
+   *
+   * @param cv the ClassVisitor this adapter delegates to
+   * @param lineNumbers the line numbers to associate with methods
+   */
+  @Requires({
+    "cv != null",
+    "ContractMethodSignatures.isLineNumberList(lineNumbers)"
+  })
+  public LineNumberingClassAdapter(ClassVisitor cv, List<Long> lineNumbers) {
+    super(Opcodes.ASM4, cv);
+    this.lineNumbers = lineNumbers;
+  }
+
+  /**
+   * Visits the specified method, adding line numbering.
+   */
+  @Override
+  public MethodVisitor visitMethod(int access, final String name, String desc,
+                                   String signature, String[] exceptions) {
+    MethodVisitor mv = cv.visitMethod(access | Opcodes.ACC_SYNTHETIC,
+                                      name, desc, signature, exceptions);
+    return new LineNumberingMethodAdapter(mv, access | Opcodes.ACC_SYNTHETIC,
+                                          name, desc) {
+      @Override
+      protected void onMethodEnter() {
+        this.lineNumbers = LineNumberingClassAdapter.this.lineNumbers;
+        super.onMethodEnter();
+      }
+    };
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/LineNumberingMethodAdapter.java b/src/com/google/java/contract/core/agent/LineNumberingMethodAdapter.java
new file mode 100644
index 0000000..882ede7
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/LineNumberingMethodAdapter.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.JavaUtils;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.commons.AdviceAdapter;
+
+import java.util.List;
+
+/**
+ * A method adapter that adds {@link #lineNumber} to the beginning of
+ * its instructions.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant(
+  "lineNumbers == null || " +
+      "ContractMethodSignatures.isLineNumberList(lineNumbers)"
+)
+abstract class LineNumberingMethodAdapter extends AdviceAdapter {
+  /**
+   * The line numbers to add to the method. This implementation always
+   * sets this field to {@code null}. Child classes must override this
+   * value before the call to {@link #onMethodEnter()} in order to get
+   * useful results.
+   */
+  protected List<Long> lineNumbers;
+
+  /**
+   * Constructs a new LineNumberingMethodAdapter.
+   *
+   * @param mv the MethodVisitor this adapter delegates to
+   * @param access the access flags of the method
+   * @param name the name of the method
+   * @param desc the descriptor of the method
+   */
+  @Requires({
+    "mv != null",
+    "name != null",
+    "desc != null"
+  })
+  public LineNumberingMethodAdapter(MethodVisitor mv, int access,
+                                    String name, String desc) {
+    super(Opcodes.ASM4, mv, access, name, desc);
+    lineNumbers = null;
+  }
+
+  @Override
+  protected void onMethodEnter() {
+    if (lineNumbers != null && !lineNumbers.isEmpty()) {
+      Long lineNumber = lineNumbers.get(0);
+      if (lineNumber != null) {
+        Label methodStart = new Label();
+        mark(methodStart);
+        mv.visitLineNumber(lineNumber.intValue(), methodStart);
+      }
+    }
+  }
+
+  @Override
+  protected void onMethodExit(int opcode) {
+  }
+
+  @Override
+  public void visitLineNumber(int line, Label start) {
+    /* Ignore original line number information. */
+  }
+
+  @Override
+  public void visitLocalVariable(String name, String desc, String signature,
+                                 Label start, Label end, int index) {
+    if (lineNumbers != null) {
+      String prefix = JavaUtils.SUCCESS_VARIABLE_PREFIX + "$";
+      if (name.startsWith(prefix)) {
+        try {
+          int no = Integer.parseInt(name.substring(prefix.length()));
+          if (no < lineNumbers.size()) {
+            Long lineNumber = lineNumbers.get(no);
+            if (lineNumber != null) {
+              mv.visitLineNumber(lineNumber.intValue(), start);
+            }
+          }
+        } catch (NumberFormatException e) {
+          /* Not the variable we are looking for. */
+        }
+      }
+    }
+    super.visitLocalVariable(name, desc, signature, start, end, index);
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/MethodContractHandle.java b/src/com/google/java/contract/core/agent/MethodContractHandle.java
new file mode 100644
index 0000000..17737d4
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/MethodContractHandle.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractKind;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.List;
+
+/**
+ * A contract handle representing a contract method with method-wide
+ * effect.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("getMethodName() != null")
+public class MethodContractHandle extends ContractHandle {
+  protected String methodName;
+
+  /**
+   * Constructs a new MethodContractHandle.
+   *
+   * @param kind the kind of this MethodContractHandle
+   * @param className the class this handle belongs to
+   * @param contractMethod the {@link MethodNode} representing this
+   * handle's method
+   * @param lineNumbers the line numbers associated with the contract
+   */
+  @Requires({
+    "kind != null",
+    "className != null",
+    "contractMethod != null"
+  })
+  @Ensures({
+    "kind == getKind()",
+    "className.equals(getClassName())",
+    "contractMethod == getContractMethod()",
+    "lineNumbers == getLineNumbers()"
+  })
+  public MethodContractHandle(ContractKind kind, String className,
+                              MethodNode contractMethod,
+                              List<Long> lineNumbers) {
+    super(kind, className, contractMethod, lineNumbers);
+    methodName = ContractMethodSignatures.getTarget(contractMethod);
+  }
+
+  public String getMethodName() {
+    return methodName;
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/PreMain.java b/src/com/google/java/contract/core/agent/PreMain.java
new file mode 100644
index 0000000..0186aa7
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/PreMain.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.ContractEnvironment;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.DebugUtils;
+import com.google.java.contract.core.util.JavaUtils;
+import org.objectweb.asm.ClassReader;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.InvocationTargetException;
+import java.security.ProtectionDomain;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * A Java agent premain class that sets up class instrumentation for
+ * contracts or can be run as a standalone program that instruments
+ * class files.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+public class PreMain {
+  @Invariant("transformer != null")
+  private static class DumpClassFileTransformer
+      implements ClassFileTransformer {
+    protected ClassFileTransformer transformer;
+
+    @Requires({
+      "parent != null",
+      "dumpDir != null"
+    })
+    public DumpClassFileTransformer(ClassFileTransformer parent,
+                                    String dumpDir) {
+      transformer = parent;
+      DebugUtils.setDumpDirectory(dumpDir);
+    }
+
+    @Override
+    public byte[] transform(ClassLoader loader, String className,
+                            Class<?> redefinedClass,
+                            ProtectionDomain protectionDomain,
+                            byte[] bytecode)
+        throws IllegalClassFormatException {
+      byte[] data = transformer.transform(loader, className, redefinedClass,
+                                          protectionDomain, bytecode);
+      if (data != null) {
+        DebugUtils.dump(className, data, Kind.CLASS);
+      }
+      return data;
+    }
+  }
+
+  private static void configure() {
+    String configClass = System.getProperty("com.google.java.contract.configurator");
+    if (configClass != null) {
+      try {
+        Class<?> clazz = Class.forName(configClass);
+        Object instance = clazz.newInstance();
+        clazz.getMethod("configure", ContractEnvironment.class)
+            .invoke(instance, new AgentContractEnvironment());
+      } catch (ClassNotFoundException e) {
+        DebugUtils.warn("agent", "cannot find configurator class");
+      } catch (NoSuchMethodException e) {
+        DebugUtils.warn("agent", "cannot find configure method");
+      } catch (InvocationTargetException e) {
+        DebugUtils.warn("agent", "configure method threw an exception: "
+                        + e.getTargetException().toString());
+      } catch (Exception e) {
+        DebugUtils.warn("agent",
+                        "error during configure method: " + e.toString());
+      }
+    }
+  }
+
+  public static void premain(String args, Instrumentation inst) {
+    ClassFileTransformer transformer = new ContractClassFileTransformer();
+
+    String dumpDir = System.getProperty("com.google.java.contract.dump");
+    if (dumpDir != null) {
+      transformer = new DumpClassFileTransformer(transformer, dumpDir);
+    }
+
+    inst.addTransformer(transformer);
+
+    configure();
+  }
+
+  public static void main(String[] args)
+      throws IllegalClassFormatException, IOException {
+    String classout =
+      System.getProperty("com.google.java.contract.classoutput");
+    /* TODO(lenh): Separate class loader for source files. */
+    instrument(args, classout, null);
+  }
+
+  public static void instrument(String[] args, String classout,
+                                ClassLoader loader)
+      throws IllegalClassFormatException, IOException {
+    ContractClassFileTransformer transformer;
+    if (loader == null) {
+      transformer = new ContractClassFileTransformer();
+    } else {
+      transformer = new ContractClassFileTransformer(loader);
+    }
+    configure();
+
+    for (String arg : args) {
+      String baseName = arg;
+      if (arg.endsWith(Kind.CLASS.extension)) {
+        baseName = baseName
+            .substring(0, baseName.length() - Kind.CLASS.extension.length());
+      }
+
+      /*
+       * Ignore helper class files, which are handled along with their
+       * interface.
+       */
+      if (baseName.endsWith(JavaUtils.HELPER_CLASS_SUFFIX)) {
+        continue;
+      }
+
+      /*
+       * Compute file names for all class files potentially
+       * involved.
+       */
+      File fileName = new File(baseName + Kind.CLASS.extension);
+      File contractFileName =
+          new File(baseName + JavaUtils.CONTRACTS_EXTENSION);
+      File helperFileName =
+          new File(baseName + JavaUtils.HELPER_CLASS_SUFFIX
+                   + Kind.CLASS.extension);
+
+      byte[] bytecode = getBytes(fileName);
+      byte[] instrumented = null;
+      byte[] instrumentedHelper = null;
+
+      File outputFileName;
+      File helperOutputFileName;
+      if (classout == null) {
+        outputFileName = new File(baseName + JavaUtils.CONTRACTED_EXTENSION);
+        helperOutputFileName =
+            new File(baseName + JavaUtils.HELPER_CLASS_SUFFIX
+                     + JavaUtils.CONTRACTED_EXTENSION);
+      } else {
+        String className = getClassName(bytecode);
+        String baseOutputName = classout + "/" + className;
+        outputFileName = new File(baseOutputName + Kind.CLASS.extension);
+        helperOutputFileName =
+            new File(baseOutputName + JavaUtils.HELPER_CLASS_SUFFIX
+                     + Kind.CLASS.extension);
+      }
+
+      /*
+       * - If argument is an interface, instrument helper, copy interface.
+       * - If argument is a contracted class, instrument class.
+       * - Otherwise, copy class file.
+       */
+      if (helperFileName.isFile()) {
+        byte[] helperBytecode = getBytes(helperFileName);
+        instrumentedHelper = transformer.transformWithDebug(helperBytecode);
+      } else if (contractFileName.isFile()) {
+        byte[] contractBytecode = getBytes(contractFileName);
+        instrumented =
+            transformer.transformWithContracts(bytecode, contractBytecode);
+      }
+
+      outputFileName.getParentFile().mkdirs();
+      FileOutputStream out = new FileOutputStream(outputFileName);
+      out.write(instrumented == null ? bytecode : instrumented);
+      out.close();
+
+      if (instrumentedHelper != null) {
+        helperOutputFileName.getParentFile().mkdirs();
+        FileOutputStream helperOut = new FileOutputStream(helperOutputFileName);
+        helperOut.write(instrumentedHelper);
+        helperOut.close();
+      }
+    }
+  }
+
+  private static byte[] getBytes(File path) throws IOException {
+    FileInputStream in = new FileInputStream(path);
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+    byte[] buffer = new byte[1024];
+    int len;
+    while ((len = in.read(buffer)) != -1) {
+      out.write(buffer, 0, len);
+    }
+    in.close();
+
+    return out.toByteArray();
+  }
+
+  private static String getClassName(byte[] bytecode)
+      throws IllegalClassFormatException {
+    try {
+      return new ClassReader(bytecode).getClassName();
+    } catch (Throwable t) {
+      /* If the class file contains errors, ASM will just crash. */
+      IllegalClassFormatException e = new IllegalClassFormatException();
+      e.initCause(t);
+      throw e;
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/SpecificationClassAdapter.java b/src/com/google/java/contract/core/agent/SpecificationClassAdapter.java
new file mode 100644
index 0000000..6cd1a1e
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/SpecificationClassAdapter.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.core.util.DebugUtils;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.List;
+
+/**
+ * Bytecode class visitor. Initiates/delegates method instrumentation
+ * to instances of {@link SpecificationMethodAdapter}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+ at AllowUnusedImport(ClassName.class)
+ at Invariant({
+  "getClassName() == null || ClassName.isBinaryName(getClassName())",
+  "getContracts() != null",
+  "getParent() != null"
+})
+class SpecificationClassAdapter extends ClassVisitor {
+  protected String className;
+  protected ContractAnalyzer contracts;
+
+  public SpecificationClassAdapter(ClassVisitor cv,
+                                   ContractAnalyzer contracts) {
+    super(Opcodes.ASM4, cv);
+    this.contracts = contracts;
+  }
+
+  @Override
+  public void visit(int version, int access, String name, String signature,
+                    String superName, String[] interfaces) {
+    super.visit(version, access, name, signature, superName, interfaces);
+    className = name;
+  }
+
+  @Override
+  public MethodVisitor visitMethod(int access, String name, String desc,
+                                   String signature, String[] exceptions) {
+    MethodVisitor mv =
+        cv.visitMethod(access, name, desc, signature, exceptions);
+    if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) != 0) {
+      return mv;
+    }
+
+    return new SpecificationMethodAdapter(this, mv, access, name, desc);
+  }
+
+  @Override
+  public void visitEnd() {
+    if (contracts != null) {
+      List<ClassContractHandle> accesses =
+          contracts.getClassHandles(ContractKind.ACCESS);
+      for (ClassContractHandle h : accesses) {
+        h.getContractMethod().accept(cv);
+      }
+
+      List<ClassContractHandle> helpers =
+          contracts.getClassHandles(ContractKind.HELPER);
+      for (ClassContractHandle h : helpers) {
+        MethodNode methodNode = h.getContractMethod();
+        DebugUtils.info("instrument", "helper method "
+                        + className + "." + methodNode.name
+                        + methodNode.desc);
+        ClassVisitor visitor = cv;
+        List<Long> lineNumbers = h.getLineNumbers();
+        if (lineNumbers != null) {
+          visitor = new LineNumberingClassAdapter(visitor, lineNumbers);
+        }
+        methodNode.accept(new ContractFixingClassAdapter(visitor));
+        h.setInjected(true);
+      }
+    }
+    super.visitEnd();
+  }
+
+  /**
+   * Returns the name of the visited class.
+   */
+  String getClassName() {
+    return className;
+  }
+
+  /**
+   * Returns the class visitor this one delegates to.
+   */
+  ClassVisitor getParent() {
+    return cv;
+  }
+
+  /**
+   * Returns the contract analyzer of the visited class.
+   */
+  ContractAnalyzer getContracts() {
+    return contracts;
+  }
+}
diff --git a/src/com/google/java/contract/core/agent/SpecificationMethodAdapter.java b/src/com/google/java/contract/core/agent/SpecificationMethodAdapter.java
new file mode 100644
index 0000000..f546269
--- /dev/null
+++ b/src/com/google/java/contract/core/agent/SpecificationMethodAdapter.java
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.agent;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.core.util.DebugUtils;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.AdviceAdapter;
+import org.objectweb.asm.commons.Method;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A bytecode method visitor that instruments the original method to
+ * add calls to contract methods, and injects these contract methods,
+ * if necessary, into the enclosing class.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+ at AllowUnusedImport({ ClassName.class, Iterables.class, Predicates.class })
+ at Invariant({
+  "methodStart != null",
+  "methodEnd != null",
+  "contracts != null",
+  "ClassName.isBinaryName(className)",
+  "methodName != null",
+  "methodDesc != null",
+  "Iterables.all(oldValueLocals, Predicates.between(0, null))",
+  "Iterables.all(signalOldValueLocals, Predicates.between(0, null))"
+})
+public class SpecificationMethodAdapter extends AdviceAdapter {
+  /*
+   * Reflection constants used in instrumentation code.
+   */
+  private static final Type CLASS_TYPE =
+      Type.getObjectType("java/lang/Class");
+  private static final Type EXCEPTION_TYPE =
+      Type.getObjectType("java/lang/Exception");
+  private static final Type CONTRACT_RUNTIME_TYPE =
+      Type.getObjectType("com/google/java/contract/core/runtime/ContractRuntime");
+  private static final Type CONTRACT_CONTEXT_TYPE =
+      Type.getObjectType("com/google/java/contract/core/runtime/ContractContext");
+  private static final Method GET_CLASS_METHOD =
+      Method.getMethod("java.lang.Class getClass()");
+  private static final Method GET_CONTEXT_METHOD =
+      Method.getMethod("com.google.java.contract.core.runtime.ContractContext "
+                       + "getContext()");
+  private static final Method TRY_ENTER_CONTRACT_METHOD =
+      Method.getMethod("boolean tryEnterContract()");
+  private static final Method LEAVE_CONTRACT_METHOD =
+      Method.getMethod("void leaveContract()");
+  private static final Method TRY_ENTER_METHOD =
+      Method.getMethod("boolean tryEnter(Object)");
+  private static final Method LEAVE_METHOD =
+      Method.getMethod("void leave(Object)");
+
+  /*
+   * Used to bracket the entire original method to catch any exception
+   * that may arise and relay it to the exceptional postconditions.
+   */
+  protected Label methodStart;
+  protected Label methodEnd;
+
+  protected ContractAnalyzer contracts;
+  protected String className;
+  protected String methodName;
+  protected String methodDesc;
+  protected Type thisType;
+
+  protected boolean statik;
+  protected boolean isConstructor;
+  protected boolean isStaticInit;
+
+  protected int contextLocal;
+  protected int checkInvariantsLocal;
+  protected List<Integer> oldValueLocals;
+  protected List<Integer> signalOldValueLocals;
+
+  protected SpecificationClassAdapter classAdapter;
+
+  protected boolean withPreconditions;
+  protected boolean withPostconditions;
+  protected boolean withInvariants;
+
+  /**
+   * Constructs a new SpecificationClassAdapter.
+   *
+   * @param ca the class adapter which has spawned this method adapter
+   * @param mv the method visitor to delegate to
+   * @param access the method access bit mask
+   * @param methodName the name of the method
+   * @param methodDesc the descriptor of the method
+   */
+  @Requires({
+    "ca != null",
+    "mv != null",
+    "methodName != null",
+    "methodDesc != null"
+  })
+  public SpecificationMethodAdapter(SpecificationClassAdapter ca,
+                                    MethodVisitor mv,
+                                    int access, String methodName,
+                                    String methodDesc) {
+    super(Opcodes.ASM4, mv, access, methodName, methodDesc);
+
+    methodStart = new Label();
+    methodEnd = new Label();
+
+    this.contracts = ca.getContracts();
+    className = ca.getClassName();
+    this.methodName = methodName;
+    this.methodDesc = methodDesc;
+    thisType = Type.getType("L" + className + ";");
+
+    statik = (access & ACC_STATIC) != 0;
+    isConstructor = methodName.equals("<init>");
+    isStaticInit = methodName.endsWith("<clinit>");
+
+    contextLocal = -1;
+    checkInvariantsLocal = -1;
+    oldValueLocals = new ArrayList<Integer>();
+    signalOldValueLocals = new ArrayList<Integer>();
+
+    classAdapter = ca;
+
+    ActivationRuleManager am = ActivationRuleManager.getInstance();
+    withPreconditions = am.hasPreconditionsEnabled(className);
+    withPostconditions = am.hasPostconditionsEnabled(className);
+    withInvariants = am.hasInvariantsEnabled(className);
+  }
+
+  /**
+   * Returns {@code true} if the specified label is resolved, that is,
+   * is associated with an offset in the bytecode of the method.
+   */
+  @Requires("label != null")
+  protected static boolean labelIsResolved(Label label) {
+    try {
+      label.getOffset();
+    } catch (IllegalStateException e) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void visitLocalVariable(String name, String desc, String signature,
+                                 Label start, Label end, int index) {
+    /*
+     * Handle bogus debug information where labels are not on
+     * instruction boundaries. EMMA, the coverage instrumenter in use
+     * at Google, produces such code.
+     */
+    if (!labelIsResolved(start)) {
+      return;
+    }
+    if (!labelIsResolved(end)) {
+      end = start;
+    }
+    super.visitLocalVariable(name, desc, signature, start, end, index);
+  }
+
+  /**
+   * Advises the method by injecting invariants, precondition
+   * assertions, and old value computations, before the original code.
+   */
+  @Override
+  protected void onMethodEnter() {
+    if (withPreconditions || withPostconditions || withInvariants) {
+      enterContractedMethod();
+
+      if (withPostconditions) {
+        allocateOldValues(ContractKind.OLD, oldValueLocals);
+        allocateOldValues(ContractKind.SIGNAL_OLD, signalOldValueLocals);
+      }
+
+      mark(methodStart);
+
+      Label skip = enterBusySection();
+
+      if (withInvariants && !statik && !isConstructor && !isStaticInit) {
+        invokeInvariants();
+      }
+
+      if (withPreconditions) {
+        invokePreconditions();
+      }
+
+      if (withPostconditions) {
+        invokeOldValues(ContractKind.OLD, oldValueLocals);
+        invokeOldValues(ContractKind.SIGNAL_OLD, signalOldValueLocals);
+      }
+
+      leaveBusySection(skip);
+    }
+  }
+
+  /**
+   * Advises the method by injecting postconditions and invariants
+   * on exit from the original code ({@code return} or {@throw}).
+   */
+  @Override
+  protected void onMethodExit(int opcode) {
+    if ((withPreconditions || withPostconditions || withInvariants)
+        && opcode != ATHROW) {
+      if (withPostconditions || withInvariants) {
+        Label skip = enterBusySection();
+
+        if (withPostconditions) {
+          Type returnType = Type.getReturnType(methodDesc);
+          int returnIndex = -1;
+          if (returnType.getSort() != Type.VOID) {
+            if (returnType.getSize() == 2) {
+              dup2();
+            } else {
+              dup();
+            }
+            returnIndex = newLocal(returnType);
+            storeLocal(returnIndex);
+          }
+          invokeCommonPostconditions(ContractKind.POST, oldValueLocals,
+                                     returnIndex);
+        }
+
+        if (withInvariants && !statik) {
+          invokeInvariants();
+        }
+
+        leaveBusySection(skip);
+      }
+      leaveContractedMethod();
+    }
+  }
+
+  /**
+   * Advises the method by injecting exceptional postconditions and
+   * invariants after the original code. This code only gets executed
+   * if an exception has been thrown (otherwise, a {@code return}
+   * instruction would have ended execution of the method already).
+   */
+  @Override
+  public void visitMaxs(int maxStack, int maxLocals) {
+    if (withPreconditions || withPostconditions || withInvariants) {
+      mark(methodEnd);
+      catchException(methodStart, methodEnd, null);
+
+      if (withPostconditions) {
+        Label skipEx = new Label();
+        dup();
+        instanceOf(EXCEPTION_TYPE);
+        ifZCmp(EQ, skipEx);
+
+        Label skip = enterBusySection();
+        int throwIndex = newLocal(EXCEPTION_TYPE);
+        checkCast(EXCEPTION_TYPE);
+        storeLocal(throwIndex);
+
+        invokeCommonPostconditions(ContractKind.SIGNAL, signalOldValueLocals,
+                                   throwIndex);
+        if (withInvariants && !statik) {
+          invokeInvariants();
+        }
+
+        loadLocal(throwIndex);
+        leaveBusySection(skip);
+
+        mark(skipEx);
+      }
+
+      /*
+       * The exception to throw is on the stack and
+       * leaveContractedMethod() does not alter that fact.
+       */
+      leaveContractedMethod();
+      throwException();
+    }
+    super.visitMaxs(maxStack, maxLocals);
+  }
+
+  /**
+   * Injects code to allocate the local variables needed to hold old
+   * values for the postconditions of the method. These variables are
+   * initialized to {@code null}.
+   *
+   * @param kind either OLD or SIGNAL_OLD
+   * @param list the list that will hold the allocated indexes
+   */
+  @Requires({
+    "kind != null",
+    "kind.isOld()",
+    "list != null"
+  })
+  protected void allocateOldValues(ContractKind kind, List<Integer> list) {
+    List<MethodContractHandle> olds =
+        contracts.getMethodHandles(kind, methodName, methodDesc, 0);
+    if (olds.isEmpty()) {
+      return;
+    }
+
+    Integer[] locals = new Integer[olds.size()];
+    for (MethodContractHandle h : olds) {
+      int k = h.getKey();
+      locals[k] = newLocal(Type.getReturnType(h.getContractMethod().desc));
+      push((String) null);
+      storeLocal(locals[k]);
+    }
+    list.addAll(Arrays.asList(locals));
+  }
+
+  /**
+   * Injects calls to old value contract methods. old value contract
+   * methods get called with, in this order:
+   *
+   * <ul>
+   * <li>the {@code this} pointer, if any;
+   * <li>and the original method's parameters.
+   * </ul>
+   *
+   * @param kind either OLD or SIGNAL_OLD
+   * @param list the list that holds the allocated old value variable
+   * indexes
+   */
+  @Requires({
+    "kind != null",
+    "kind.isOld()",
+    "list != null"
+  })
+  protected void invokeOldValues(ContractKind kind, List<Integer> list) {
+    List<MethodContractHandle> olds =
+        contracts.getMethodHandles(kind, methodName, methodDesc, 0);
+    if (olds.isEmpty()) {
+      return;
+    }
+
+    for (MethodContractHandle h : olds) {
+      MethodNode contractMethod = injectContractMethod(h);
+      int k = h.getKey();
+
+      if (!statik) {
+        loadThis();
+      }
+      loadArgs();
+      invokeContractMethod(contractMethod);
+
+      storeLocal(list.get(k));
+    }
+  }
+
+  /**
+   * Injects calls to invariant contract methods. Invariant contract
+   * methods get called with the {@code this} pointer, if any.
+   */
+  protected void invokeInvariants() {
+    ClassContractHandle h = contracts.getClassHandle(ContractKind.INVARIANT);
+    if (h == null) {
+      return;
+    }
+
+    MethodNode contractMethod = injectContractMethod(h);
+
+    Label skipInvariants = new Label();
+    if (isConstructor) {
+      loadThis();
+      invokeVirtual(thisType, GET_CLASS_METHOD);
+      loadThisClass();
+      ifCmp(CLASS_TYPE, NE, skipInvariants);
+    } else {
+      loadLocal(checkInvariantsLocal);
+      ifZCmp(EQ, skipInvariants);
+    }
+
+    if (!statik) {
+      loadThis();
+    }
+    invokeContractMethod(contractMethod);
+
+    mark(skipInvariants);
+  }
+
+  /**
+   * Injects calls to precondition contract methods. Precondition
+   * contract methods get called with, in this order:
+   *
+   * <ul>
+   * <li>the {@code this} pointer, if any;
+   * <li>and the original method's parameters.
+   * </ul>
+   */
+  protected void invokePreconditions() {
+    MethodContractHandle h =
+        contracts.getMethodHandle(ContractKind.PRE, methodName, methodDesc, 0);
+    if (h == null) {
+      return;
+    }
+
+    MethodNode contractMethod = injectContractMethod(h);
+    if (!statik) {
+      loadThis();
+    }
+    loadArgs();
+    invokeContractMethod(contractMethod);
+  }
+
+  /**
+   * Injects calls to postcondition (or exceptional postcondition)
+   * contract methods. Postcondition contract methods get called with,
+   * in this order:
+   *
+   * <ul>
+   * <li>the {@code this} pointer, if any;
+   * <li>the original method's parameters;
+   * <li>the return value, if the original method is not void, or the
+   * exception object;
+   * <li>and old values if any.
+   * </ul>
+   *
+   * @param kind the kind of postcondition contract to invoke
+   * @param oldLocals a list of old value variables
+   * @param extraIndex the index of the local variable that holds the
+   * return value, or exception object, of the method, or -1 if none
+   */
+  @Requires({
+    "kind != null",
+    "kind.isPostcondition()",
+    "oldLocals != null",
+    "extraIndex >= -1"
+  })
+  protected void invokeCommonPostconditions(ContractKind kind,
+      List<Integer> oldLocals, int extraIndex) {
+    MethodContractHandle h =
+        contracts.getMethodHandle(kind, methodName, methodDesc,
+                                  getPostDescOffset(oldLocals, extraIndex));
+    if (h == null) {
+      return;
+    }
+
+    MethodNode contractMethod = injectContractMethod(h);
+
+    if (!statik) {
+      loadThis();
+    }
+    loadArgs();
+
+    if (extraIndex != -1) {
+      loadLocal(extraIndex);
+    }
+
+    for (Integer oldIndex : oldLocals) {
+      loadLocal(oldIndex);
+    }
+
+    invokeContractMethod(contractMethod);
+  }
+
+  /**
+   * Computes the method descriptor offset of a postcondition (or an
+   * exceptional postcondition). The method descriptor offset is the
+   * number of extra arguments the contract method has in addition to
+   * those inherited from the original method.
+   *
+   * @param oldLocals the list of old value variables
+   * @param extraIndex the local variable index of an extra parameter,
+   * or -1 if none
+   */
+  @Requires({
+    "oldLocals != null",
+    "extraIndex >= -1"
+  })
+  @Ensures("result >= 0")
+  protected int getPostDescOffset(List<Integer> oldLocals, int extraIndex) {
+    int off = 0;
+    if (extraIndex != -1) {
+      ++off;
+    }
+    off += oldLocals.size();
+    return off;
+  }
+
+  /**
+   * Injects the specified contract method code into the current
+   * class, and returns a new Method object representing the injected
+   * method. This is done by bypassing the SpecificationClassAdapter
+   * and talking directly to its parent (usually, a class writer).
+   *
+   * @param handle the handle from the code pool that holds code and
+   * meta-information about the contract method
+   * @return the method node to invoke
+   */
+  @Requires("handle != null")
+  @Ensures("result != null")
+  protected MethodNode injectContractMethod(ContractHandle handle) {
+    MethodNode methodNode = handle.getContractMethod();
+
+    if (!handle.isInjected()) {
+      DebugUtils.info("instrument", "contract method "
+                      + className + "." + methodNode.name
+                      + methodNode.desc);
+      ClassVisitor cv = classAdapter.getParent();
+      List<Long> lineNumbers = handle.getLineNumbers();
+      if (lineNumbers != null) {
+        cv = new LineNumberingClassAdapter(cv, lineNumbers);
+      }
+      methodNode.accept(new ContractFixingClassAdapter(cv));
+      handle.setInjected(true);
+    }
+
+    return methodNode;
+  }
+
+  @Requires("contractMethod != null")
+  protected void invokeContractMethod(MethodNode contractMethod) {
+    if (!statik) {
+      mv.visitMethodInsn(INVOKESPECIAL, className,
+                         contractMethod.name, contractMethod.desc);
+    } else {
+      mv.visitMethodInsn(INVOKESTATIC, className,
+                         contractMethod.name, contractMethod.desc);
+    }
+  }
+
+  /**
+   * Marks the beginning of a busy section. A busy section is skipped
+   * if the context is already busy.
+   */
+  @Requires({
+    "contextLocal >= 0",
+    "checkInvariantsLocal >= 0"
+  })
+  @Ensures("result != null")
+  protected Label enterBusySection() {
+    Label skip = new Label();
+    loadLocal(contextLocal);
+    invokeVirtual(CONTRACT_CONTEXT_TYPE, TRY_ENTER_CONTRACT_METHOD);
+    ifZCmp(EQ, skip);
+    return skip;
+  }
+
+  /**
+   * Marks the end of a busy section.
+   */
+  @Requires({
+    "contextLocal >= 0",
+    "skip != null"
+  })
+  protected void leaveBusySection(Label skip) {
+    loadLocal(contextLocal);
+    invokeVirtual(CONTRACT_CONTEXT_TYPE, LEAVE_CONTRACT_METHOD);
+    mark(skip);
+  }
+
+  /**
+   * Loads the static class object this method belongs to on the
+   * stack.
+   */
+  protected void loadThisClass() {
+    visitLdcInsn(thisType);
+  }
+
+  /**
+   * Retrieves busy state of the current object.
+   */
+  @Ensures({
+    "contextLocal >= 0",
+    "checkInvariantsLocal >= 0"
+  })
+  protected void enterContractedMethod() {
+    contextLocal = newLocal(CONTRACT_CONTEXT_TYPE);
+    checkInvariantsLocal = newLocal(Type.BOOLEAN_TYPE);
+    invokeStatic(CONTRACT_RUNTIME_TYPE, GET_CONTEXT_METHOD);
+    dup();
+    storeLocal(contextLocal);
+    if (statik) {
+      loadThisClass();
+    } else {
+      loadThis();
+    }
+    invokeVirtual(CONTRACT_CONTEXT_TYPE, TRY_ENTER_METHOD);
+    storeLocal(checkInvariantsLocal);
+  }
+
+  /**
+   * Cancels busy state of the current object.
+   */
+  @Requires("contextLocal >= 0")
+  protected void leaveContractedMethod() {
+    Label skip = new Label();
+    loadLocal(checkInvariantsLocal);
+    ifZCmp(EQ, skip);
+
+    loadLocal(contextLocal);
+    if (statik) {
+      loadThisClass();
+    } else {
+      loadThis();
+    }
+    invokeVirtual(CONTRACT_CONTEXT_TYPE, LEAVE_METHOD);
+
+    mark(skip);
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/AbstractTypeBuilder.java b/src/com/google/java/contract/core/apt/AbstractTypeBuilder.java
new file mode 100644
index 0000000..2049d44
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/AbstractTypeBuilder.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModel;
+import com.google.java.contract.core.model.TypeName;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.util.ElementScanner6;
+
+/**
+ * Abstract base class providing annotation processing facilities
+ * used to build types.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at Invariant("utils != null")
+abstract class AbstractTypeBuilder
+    extends ElementScanner6<Void, ElementModel> {
+  protected FactoryUtils utils;
+
+  protected DiagnosticManager diagnosticManager;
+
+  @Requires("utils != null")
+  protected AbstractTypeBuilder(FactoryUtils utils,
+                                DiagnosticManager diagnosticManager) {
+    this.utils = utils;
+    this.diagnosticManager = diagnosticManager;
+  }
+
+  /**
+   * A global iterator to use to get contract annotation line number
+   * information.
+   */
+  protected Iterator<Long> rootLineNumberIterator;
+
+  /**
+   * Creates a blank {@code ContractAnnotationModel} from
+   * an {@code AnnotationMirror}. The returned model is created with
+   * the correct properties for the provided context but does not
+   * contain any of the clauses from {@code annotation}.
+   *
+   * @param parent the target of the annotation
+   * @param annotation the annotation
+   * @param primary whether this is a primary contract annotation
+   * @param owner the owner of this annotation
+   * @return the contract model of this annotation
+   */
+  @Requires({
+    "parent != null",
+    "annotation != null",
+    "owner != null",
+    "utils.isContractAnnotation(annotation)"
+  })
+  @Ensures("result != null")
+  private ContractAnnotationModel createBlankContractModel(Element parent,
+      AnnotationMirror annotation, boolean primary, ClassName owner) {
+    ElementKind kind = utils.getAnnotationKindForName(annotation);
+
+    boolean virtual;
+    TypeName returnType;
+    switch (parent.getKind()) {
+      default:
+        virtual =
+            parent.getKind()
+            != javax.lang.model.element.ElementKind.INTERFACE;
+        returnType = null;
+        break;
+      case CONSTRUCTOR:
+      case METHOD:
+        virtual =
+            parent.getEnclosingElement().getKind()
+            != javax.lang.model.element.ElementKind.INTERFACE;
+        ExecutableElement method = (ExecutableElement) parent;
+        switch (method.getReturnType().getKind()) {
+          case VOID:
+            /* For void methods. */
+            returnType = utils.getTypeNameForType(method.getReturnType());
+            break;
+          case NONE:
+            /* For constructors. */
+            returnType = null;
+            break;
+          case PACKAGE:
+            /* Should not happen. */
+            throw new RuntimeException(
+                "ExecutableElement has PACKAGE return type");
+          default:
+            returnType = utils.getTypeNameForType(
+                utils.typeUtils.erasure(method.getReturnType()));
+        }
+    }
+
+    return new ContractAnnotationModel(kind, primary, virtual,
+                                       owner, returnType);
+  }
+
+  /**
+   * Creates a {@code ContractAnnotationModel} from
+   * an {@code AnnotationMirror}.
+   *
+   * @param parent the target of the annotation
+   * @param annotation the annotation
+   * @param primary whether this is a primary contract annotation
+   * @param owner the owner of this annotation
+   * @return the contract model of this annotation, or {@code null} if
+   * the annotation contains no contract (no or empty value)
+   */
+  @Requires({
+    "parent != null",
+    "annotation != null",
+    "owner != null",
+    "utils.isContractAnnotation(annotation)"
+  })
+  protected ContractAnnotationModel createContractModel(Element parent,
+      AnnotationMirror annotation, boolean primary, ClassName owner) {
+    ContractAnnotationModel model = createBlankContractModel(
+        parent, annotation, primary, owner);
+    List<Long> lineNumbers = null;
+    if (rootLineNumberIterator == null) {
+      lineNumbers = getLineNumbers(parent, annotation);
+    }
+
+    AnnotationValue lastAnnotationValue = null;
+    for (AnnotationValue annotationValue :
+         annotation.getElementValues().values()) {
+      @SuppressWarnings("unchecked")
+      List<? extends AnnotationValue> values =
+          (List<? extends AnnotationValue>) annotationValue.getValue();
+
+      Iterator<? extends AnnotationValue> iterValue = values.iterator();
+      Iterator<Long> iterLineNumber;
+      if (rootLineNumberIterator != null) {
+        iterLineNumber = rootLineNumberIterator;
+      } else {
+        iterLineNumber = lineNumbers.iterator();
+      }
+      while (iterValue.hasNext()) {
+        String value = (String) iterValue.next().getValue();
+        Long lineNumber =
+            iterLineNumber.hasNext() ? iterLineNumber.next() : null;
+        model.addValue(value, lineNumber);
+      }
+      lastAnnotationValue = annotationValue;
+    }
+    if (model.getValues().isEmpty()) {
+      diagnosticManager.warning("No contracts specified in annotation.",
+                                null, 0, 0, 0,
+                                parent, annotation, lastAnnotationValue);
+      return null;
+    }
+    AnnotationSourceInfo sourceInfo =
+        new AnnotationSourceInfo(parent, annotation, lastAnnotationValue,
+                                 model.getValues());
+    model.setSourceInfo(sourceInfo);
+    return model;
+  }
+
+  /**
+   * Visits an annotation and adds a corresponding node to the
+   * specified Element.
+   *
+   * Despite the name, this method is not inherited through any
+   * visitor interface. It is not intended for external calls.
+   *
+   * @param parent the target of the annotation
+   * @param annotation the annotation
+   * @param primary whether this is a primary contract annotation
+   * @param owner the owner of this annotation
+   * @param p the element to add the created annotation to
+   *
+   * @see ContractAnnotationModel
+   */
+  @Requires({
+    "parent != null",
+    "annotation != null",
+    "owner != null",
+    "p != null"
+  })
+  protected void visitAnnotation(
+      Element parent, AnnotationMirror annotation,
+      boolean primary, ClassName owner, ElementModel p) {
+    if (utils.isContractAnnotation(annotation)) {
+      ContractAnnotationModel model =
+          createContractModel(parent, annotation, primary, owner);
+      if (model != null) {
+        p.addEnclosedElement(model);
+      }
+    }
+  }
+
+  /**
+   * Returns the line numbers associated with {@code annotation} if
+   * available.
+   */
+  @Requires({
+    "parent != null",
+    "annotation != null"
+  })
+  @Ensures("result != null")
+  @SuppressWarnings("unchecked")
+  protected List<Long> getLineNumbers(Element parent,
+                                      AnnotationMirror annotation) {
+    if (JavaUtils.classExists("com.sun.source.util.Trees")) {
+      try {
+        return (List<Long>) Class
+            .forName("com.google.java.contract.core.apt.JavacUtils")
+            .getMethod("getLineNumbers", ProcessingEnvironment.class,
+                       Element.class, AnnotationMirror.class)
+            .invoke(null, utils.processingEnv, parent, annotation);
+      } catch (Exception e) {
+        return Collections.emptyList();
+      }
+    } else {
+      return Collections.emptyList();
+    }
+  }
+
+  /**
+   * Returns the import statements in effect in the compilation unit
+   * containing {@code element}.
+   */
+  @Requires("element != null")
+  @Ensures("result != null")
+  @SuppressWarnings("unchecked")
+  protected Set<String> getImportNames(Element element) {
+    if (JavaUtils.classExists("com.sun.source.util.Trees")) {
+      try {
+        return (Set<String>) Class
+            .forName("com.google.java.contract.core.apt.JavacUtils")
+            .getMethod("getImportNames", ProcessingEnvironment.class,
+                       Element.class)
+            .invoke(null, utils.processingEnv, element);
+      } catch (Exception e) {
+        return Collections.emptySet();
+      }
+    } else {
+      return Collections.emptySet();
+    }
+  }
+
+  /**
+   * Scans a list of annotations and call
+   * {@link #visitAnnotation(Element,AnnotationMirror,boolean,ClassName,ElementModel)}
+   * on each one of them, in order.
+   *
+   * @see ContractAnnotationModel
+   */
+  @Requires({
+    "parent != null",
+    "owner != null",
+    "p != null"
+  })
+  protected void scanAnnotations(Element parent,
+      boolean primary, ClassName owner, ElementModel p) {
+    for (AnnotationMirror ann : parent.getAnnotationMirrors()) {
+      visitAnnotation(parent, ann, primary, owner, p);
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/AnnotationProcessor.java b/src/com/google/java/contract/core/apt/AnnotationProcessor.java
new file mode 100644
index 0000000..732b7ba
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/AnnotationProcessor.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Options;
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.util.DebugUtils;
+import com.google.java.contract.core.util.ElementScanner;
+import com.google.java.contract.core.util.SyntheticJavaFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementScanner6;
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * A JSR 269 annotation processor that builds contract Java source
+ * files from annotated classes, and compiles them.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at AllowUnusedImport(ElementKind.class)
+ at SupportedAnnotationTypes("*")
+ at SupportedOptions({
+  AnnotationProcessor.OPT_DEBUG,
+  AnnotationProcessor.OPT_DUMP,
+  AnnotationProcessor.OPT_SOURCEPATH,
+  AnnotationProcessor.OPT_CLASSPATH,
+  AnnotationProcessor.OPT_CLASSOUTPUT,
+  AnnotationProcessor.OPT_DEPSPATH,
+  AnnotationProcessor.OPT_EXPERIMENTAL
+})
+public class AnnotationProcessor extends AbstractProcessor {
+  /**
+   * This option adds instructions for a debug trace to contract
+   * code. For the trace to actually appear at run time, the
+   * {@code com.google.java.contract.log.contract} property must be {@code true}.
+   */
+  protected static final String OPT_DEBUG = "com.google.java.contract.debug";
+
+  /**
+   * This option dumps the generated Java source files in the
+   * specified directory (defaults to {@code contracts_for_java.out}).
+   */
+  protected static final String OPT_DUMP = "com.google.java.contract.dump";
+
+  /**
+   * This option sets the source path for the compilation of the
+   * generated source files. It should be the same as the class path
+   * for the sources themselves.
+   */
+  protected static final String OPT_SOURCEPATH = "com.google.java.contract.sourcepath";
+
+  /**
+   * This option sets the class path for the compilation of the
+   * generated source files. It should be the same as the class path
+   * for the sources themselves.
+   */
+  protected static final String OPT_CLASSPATH = "com.google.java.contract.classpath";
+
+  /**
+   * This option sets the class output path for the compilation of the
+   * generated source files.
+   */
+  protected static final String OPT_CLASSOUTPUT = "com.google.java.contract.classoutput";
+
+  /**
+   * This option sets the path for source dependency auxiliary files.
+   *
+   * @see SourcePreprocessor
+   */
+  protected static final String OPT_DEPSPATH = "com.google.java.contract.depspath";
+
+  /**
+   * This option enables experimental Contracts for Java features. <em>These
+   * features may or may not be included in future releases, or
+   * change, without warning.</em>
+   */
+  protected static final String OPT_EXPERIMENTAL = "com.google.java.contract.experimental";
+
+  protected TypeFactory factory;
+  protected FactoryUtils utils;
+
+  protected String sourcePath;
+  protected String classPath;
+  protected String outputDirectory;
+
+  protected boolean debug;
+  protected boolean dump;
+
+  @Override
+  public synchronized void init(ProcessingEnvironment processingEnv) {
+    super.init(processingEnv);
+
+    Map<String, String> options = processingEnv.getOptions();
+    debug = options.containsKey(OPT_DEBUG);
+    dump = options.containsKey(OPT_DUMP);
+    String dumpDir = options.get(OPT_DUMP);
+    if (dumpDir != null) {
+      DebugUtils.setDumpDirectory(dumpDir);
+    }
+
+    utils = new FactoryUtils(processingEnv);
+    factory = new TypeFactory(utils, options.get(OPT_DEPSPATH));
+
+    setupPaths();
+  }
+
+  @Override
+  public SourceVersion getSupportedSourceVersion() {
+    return SourceVersion.latest();
+  }
+
+  @Override
+  public boolean process(Set<? extends TypeElement> annotations,
+                         RoundEnvironment roundEnv) {
+    Set<TypeElement> rootElements = getContractedRootElements(roundEnv);
+    if (rootElements.isEmpty()) {
+      return false;
+    }
+
+    DiagnosticManager diagnosticManager = new DiagnosticManager();
+
+    List<TypeModel> types = createTypes(rootElements, diagnosticManager);
+    boolean success = diagnosticManager.getErrorCount() == 0;
+
+    ArrayList<SyntheticJavaFile> sources =
+        new ArrayList<SyntheticJavaFile>(types.size());
+    if (success) {
+      for (TypeModel type : types) {
+        ContractWriter writer = new ContractWriter(debug);
+        type.accept(writer);
+        sources.add(new SyntheticJavaFile(type.getName().getBinaryName(),
+                                          writer.toByteArray(),
+                                          writer.getLineNumberMap()));
+      }
+
+      if (dump) {
+        dumpSources(types, sources);
+      }
+
+      try {
+        ContractJavaCompiler compiler =
+            new ContractJavaCompiler(sourcePath, classPath, outputDirectory);
+        CompilationTask task = compiler.getTask(sources, diagnosticManager);
+        success = task.call();
+      } catch (IOException e) {
+        throw new RuntimeException(e);
+      }
+    }
+
+    if (!success || diagnosticManager.getCount() != 0) {
+      for (DiagnosticManager.Report r : diagnosticManager) {
+        printDiagnostic(r);
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Sets class and output paths from command-line options.
+   */
+  private void setupPaths() {
+    sourcePath = processingEnv.getOptions().get(OPT_SOURCEPATH);
+    classPath = processingEnv.getOptions().get(OPT_CLASSPATH);
+    outputDirectory = processingEnv.getOptions().get(OPT_CLASSOUTPUT);
+
+    /*
+     * Not using instanceof here because than in every case the JVM
+     * tries to load the JavacProcessingEnvironment-class file which,
+     * for instance, is not possible with an IBM JVM.
+     *
+     * TODO(lenh): This may not work; use reflection call instead.
+     */
+    if (processingEnv.getClass().getName().equals(
+            "com.sun.tools.javac.processing.JavacProcessingEnvironment")) {
+      JavacProcessingEnvironment javacEnv =
+          (JavacProcessingEnvironment) processingEnv;
+      Options options = Options.instance(javacEnv.getContext());
+
+      if (sourcePath == null) {
+        sourcePath = options.get(OptionName.SOURCEPATH);
+      }
+
+      if (classPath == null) {
+        String classPath1 = options.get(OptionName.CP);
+        String classPath2 = options.get(OptionName.CLASSPATH);
+        if (classPath1 != null) {
+          if (classPath2 != null) {
+            classPath = classPath1 + File.pathSeparator + classPath2;
+          } else {
+            classPath = classPath1;
+          }
+        } else {
+          classPath = classPath2;
+        }
+      }
+
+      if (outputDirectory == null) {
+        outputDirectory = options.get(OptionName.D);
+      }
+    }
+  }
+
+  /**
+   * Prints {@code diag} with any additional contract code information
+   * available.
+   */
+  @Requires("r != null")
+  protected void printDiagnostic(DiagnosticManager.Report r) {
+    Messager messager = processingEnv.getMessager();
+    if (r.getElement() == null) {
+      messager.printMessage(r.getKind(), r.getMessage(null));
+    } else {
+      messager.printMessage(r.getKind(), r.getMessage(null), r.getElement(),
+                            r.getAnnotationMirror(), r.getAnnotationValue());
+    }
+  }
+
+  /**
+   * Dumps the computed Java source files in the dump directory of
+   * Contracts for Java.
+   */
+  @Requires({
+     "types != null",
+     "sources != null",
+     "types.size() == sources.size()"
+  })
+  protected void dumpSources(List<TypeModel> types,
+                             List<SyntheticJavaFile> sources) {
+    Iterator<TypeModel> itType = types.iterator();
+    Iterator<SyntheticJavaFile> itFile = sources.iterator();
+    while (itType.hasNext() && itFile.hasNext()) {
+      TypeModel type = itType.next();
+      SyntheticJavaFile file = itFile.next();
+      DebugUtils.dump(type.getName().getBinaryName(),
+                      file.getCharContent(true).toString().getBytes(),
+                      Kind.SOURCE);
+    }
+  }
+
+  /**
+   * Builds {@link TypeModel} objects from the {@code roots}. The
+   * types built contain contract methods. Helper types are created
+   * for interfaces.
+   */
+  @Requires({
+    "roots != null",
+    "diagnosticManager != null"
+  })
+  @Ensures({
+    "result != null",
+    "result.size() >= roots.size()",
+    "result.size() <= 2 * roots.size()"
+  })
+  protected List<TypeModel> createTypes(Set<TypeElement> roots,
+                                        DiagnosticManager diagnosticManager) {
+    boolean errors = false;
+
+    /*
+     * Extract all type names that will be part of this compilation
+     * task.
+     */
+    final HashSet<String> knownTypeNames = new HashSet<String>();
+    for (TypeElement r : roots) {
+      ElementScanner6<Void, Void> visitor =
+          new ElementScanner6<Void, Void>() {
+            @Override
+            public Void visitType(TypeElement e, Void p) {
+              knownTypeNames.add(e.getQualifiedName().toString());
+              return super.visitType(e, p);
+            }
+          };
+      r.accept(visitor, null);
+    }
+    /*
+     * Mark annotations inherited from classes compiled in the same
+     * task as weak so we don't generate stubs for them later on. This
+     * prevents name clashes due to erasure.
+     */
+    ArrayList<TypeModel> undecoratedTypes =
+        new ArrayList<TypeModel>(roots.size());
+    for (TypeElement r : roots) {
+      TypeModel type = factory.createType(r, diagnosticManager);
+      ElementScanner annotator =
+          new ElementScanner() {
+            @Override
+            public void visitContractAnnotation(
+                ContractAnnotationModel annotation) {
+              if (annotation.isVirtual()
+                  && knownTypeNames.contains(
+                      annotation.getOwner().getQualifiedName())) {
+                annotation.setWeakVirtual(true);
+              }
+            }
+          };
+      type.accept(annotator);
+      undecoratedTypes.add(type);
+    }
+    /*
+     * Decorate the type models with contract methods and create
+     * helper types.
+     */
+    ArrayList<TypeModel> types =
+        new ArrayList<TypeModel>(undecoratedTypes.size());
+    for (TypeModel type : undecoratedTypes) {
+      ClassContractCreator creator =
+          new ClassContractCreator(diagnosticManager);
+      type.accept(creator);
+      TypeModel helper = creator.getHelperType();
+      types.add(type);
+      if (helper != null) {
+        types.add(helper);
+      }
+    }
+
+    return types;
+  }
+
+  /**
+   * Returns the set of root elements that contain contracts.
+   * Contracts can have been directly declared as annotations or inherited
+   * through the hierarchy.
+   *
+   * @param annotations the set of annotations to look for
+   * @param roundEnv the environment to get elements from
+   */
+  @Requires("roundEnv != null")
+  @Ensures("result != null")
+  protected Set<TypeElement> getContractedRootElements(
+      RoundEnvironment roundEnv) {
+    Set<? extends Element> allElements = roundEnv.getRootElements();
+    Set<TypeElement> contractedRootElements =
+        new HashSet<TypeElement>(allElements.size());
+
+    ContractFinder cf = new ContractFinder(utils);
+    for (Element e : allElements) {
+      if (e.accept(cf, null)) {
+        contractedRootElements.add(getRootElement(e));
+      }
+    }
+
+    return contractedRootElements;
+  }
+
+  /**
+   * Returns the top-level type element enclosing {@code element}.
+   */
+  @Requires({
+    "element != null",
+    "element.getKind() != ElementKind.PACKAGE",
+    "element.getKind() != ElementKind.OTHER"
+  })
+  @Ensures("element != null")
+  protected static TypeElement getRootElement(Element element) {
+    if (element.getKind().isClass() || element.getKind().isInterface()) {
+      TypeElement type = (TypeElement) element;
+      if (!type.getNestingKind().isNested()) {
+        return type;
+      }
+    }
+
+    return getRootElement(element.getEnclosingElement());
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/AnnotationSourceInfo.java b/src/com/google/java/contract/core/apt/AnnotationSourceInfo.java
new file mode 100644
index 0000000..717b9b5
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/AnnotationSourceInfo.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+
+/**
+ * Source-tracking information, for error reporting.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "element != null",
+  "annotationMirror != null",
+  "annotationValue != null",
+  "code != null",
+  "!code.isEmpty()",
+  "!code.contains(null)"
+})
+public class AnnotationSourceInfo {
+  protected Element element;
+  protected AnnotationMirror annotationMirror;
+  protected AnnotationValue annotationValue;
+  protected List<String> code;
+
+  @Requires({
+    "element != null",
+    "annotationMirror != null",
+    "annotationValue != null",
+    "code != null",
+    "!code.isEmpty()"
+  })
+  @Ensures({
+    "element == getElement()",
+    "annotationMirror == getAnnotationMirror()",
+    "annotationValue == getAnnotationValue()",
+    "code.equals(getCode())"
+  })
+  public AnnotationSourceInfo(Element element,
+      AnnotationMirror annotationMirror, AnnotationValue annotationValue,
+      List<String> code) {
+    this.element = element;
+    this.annotationMirror = annotationMirror;
+    this.annotationValue = annotationValue;
+    this.code = new ArrayList<String>(code);
+  }
+
+  @Ensures("result != null")
+  public AnnotationMirror getAnnotationMirror() {
+    return annotationMirror;
+  }
+
+  @Ensures("result != null")
+  public AnnotationValue getAnnotationValue() {
+    return annotationValue;
+  }
+
+  @Ensures({
+    "result != null",
+    "!result.isEmpty()"
+  })
+  public List<String> getCode() {
+    return code;
+  }
+
+  @Ensures("result != null")
+  public Element getElement() {
+    return element;
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ClassContractCreator.java b/src/com/google/java/contract/core/apt/ClassContractCreator.java
new file mode 100644
index 0000000..23ec766
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ClassContractCreator.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import static com.google.java.contract.core.apt.ContractCreation.createContractMethods;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ContractMethodModel;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.HelperTypeModel;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.util.ElementScanner;
+
+/**
+ * Element visitor responsible for decorating a {@link TypeModel}
+ * object with class-wide contract code elements. Delegates
+ * method-wide contracts to {@link MethodContractCreator}.
+ *
+ * <p>Contracts are combined together into a single contract method,
+ * which evaluates the contracts. Moreover, each primary annotation
+ * also creates a helper method called a primary contract method.
+ *
+ * <p>A primary contract method only evaluates the current class
+ * invariant, ignoring inherited contracts. It is called by children
+ * of the class to work around access restrictions.
+ *
+ * <p>Interface contracts do not have a primary implementation as
+ * interfaces have no code body of their own. Since there can also
+ * be no access restrictions in interface contracts, they are simply
+ * inlined.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "diagnosticManager != null",
+  "transformer != null"
+})
+public class ClassContractCreator extends ElementScanner {
+  protected DiagnosticManager diagnosticManager;
+
+  protected TypeModel type;
+  protected TypeModel helperType;
+  protected ContractMethodModel invariant;
+
+  protected ContractExpressionTransformer transformer;
+
+  /**
+   * Constructs a new ClassContractCreator.
+   */
+  @Requires("diagnosticManager != null")
+  public ClassContractCreator(DiagnosticManager diagnosticManager) {
+    this.diagnosticManager = diagnosticManager;
+    type = null;
+    helperType = null;
+    invariant = null;
+    transformer = new ContractExpressionTransformer(diagnosticManager, false);
+  }
+
+  public TypeModel getHelperType() {
+    return helperType;
+  }
+
+  @Override
+  public void visitType(TypeModel type) {
+    if (this.type != null) {
+      ClassContractCreator creator =
+          new ClassContractCreator(diagnosticManager);
+      type.accept(creator);
+      if (creator.getHelperType() != null) {
+        this.type.addEnclosedElement(creator.getHelperType());
+      }
+      return;
+    }
+    this.type = type;
+    if (type.getKind() == ElementKind.INTERFACE) {
+      helperType = new HelperTypeModel(type);
+      super.visitType(helperType);
+    } else {
+      super.visitType(type);
+    }
+  }
+
+  @Override
+  public void visitMethod(MethodModel method) {
+    method.accept(new MethodContractCreator(diagnosticManager));
+  }
+
+  @Override
+  public void visitContractAnnotation(ContractAnnotationModel annotation) {
+    if (!annotation.getKind().equals(ElementKind.INVARIANT)) {
+      throw new IllegalArgumentException();
+    }
+    ContractExpressionCreationTrait trait =
+        new ContractExpressionCreationTrait(transformer) {
+          @Override
+          public String getExceptionName() {
+            return "com.google.java.contract.InvariantError";
+          }
+        };
+    invariant = createContractMethods(trait, invariant, annotation);
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractCreation.java b/src/com/google/java/contract/core/apt/ContractCreation.java
new file mode 100644
index 0000000..3afbcb0
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractCreation.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.core.model.ContractMethodModel;
+import com.google.java.contract.core.model.ContractVariance;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModifier;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.TypeName;
+import com.google.java.contract.core.model.VariableModel;
+import com.google.java.contract.core.util.Elements;
+import com.google.java.contract.core.util.JavaTokenizer.Token;
+import com.google.java.contract.core.util.JavaTokenizer.TokenKind;
+import com.google.java.contract.core.util.JavaUtils;
+import com.google.java.contract.core.util.PushbackTokenizer;
+
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Utility methods for contract creators.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class ContractCreation {
+  static final String RAISE_METHOD =
+      "com.google.java.contract.core.runtime.ContractRuntime.raise";
+
+  /**
+   * Returns {@code code} with all unqualified or this-qualified
+   * identifiers followed by an open parenthesis rebased to
+   * {@code that}. Unqualified identifiers in {@code whitelist}
+   * are not subject to this change.
+   */
+  @Requires({
+    "code != null",
+    "that != null"
+  })
+  @Ensures("result != null")
+  static String rebaseLocalCalls(String code, String that,
+                                 Set<String> whitelist) {
+    StringBuilder buffer = new StringBuilder();
+    PushbackTokenizer tokenizer = new PushbackTokenizer(new StringReader(code));
+    boolean qualified = false;
+    while (tokenizer.hasNext()) {
+      Token token = tokenizer.next();
+      if (!qualified && token.kind == TokenKind.WORD
+          && (whitelist == null || !whitelist.contains(token.text))) {
+        if (token.text.equals("this")) {
+          buffer.append("( ");
+          buffer.append(JavaUtils.BEGIN_GENERATED_CODE);
+          buffer.append(that);
+          buffer.append(JavaUtils.END_GENERATED_CODE);
+          buffer.append(" )");
+        } else {
+          if (JavaUtils.lookingAt(tokenizer, "(")) {
+            buffer.append(JavaUtils.BEGIN_GENERATED_CODE);
+            buffer.append(that);
+            buffer.append(".");
+            buffer.append(JavaUtils.END_GENERATED_CODE);
+            buffer.append(token.text);
+          } else {
+            buffer.append(token.text);
+          }
+        }
+      } else {
+        buffer.append(token.text);
+      }
+      qualified = token.text.equals(".");
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Builds a contract method body from the {@code trait}.
+   *
+   * @param contract the contract method to add the clauses to
+   * @param trait the trait to get contract code information from
+   * @param annotation the source of the contract
+   */
+  @Requires({
+    "contract != null",
+    "trait != null",
+    "annotation != null"
+  })
+  static void addContractClauses(ContractMethodModel contract,
+                                 ContractCreationTrait trait,
+                                 ContractAnnotationModel annotation) {
+    ContractKind kind = getContractKind(annotation);
+
+    Iterator<String> itCode = trait.getExpressions().iterator();
+    Iterator<String> itMsg = trait.getMessages().iterator();
+    Iterator<String> itComment = trait.getSourceExpressions().iterator();
+    int successVariableCount = 0;
+    int exceptionVariableCount = 0;
+    while (itCode.hasNext()) {
+      StringBuilder buffer = new StringBuilder();
+      String expr = itCode.next();
+      String exprMsg = itMsg.next();
+      String exprComment = itComment.next();
+
+      /*
+       * Evaluate predicate. The success variable is first assigned a
+       * dummy value so as to be able to track the start of the
+       * evaluation in the generated bytecode.
+       */
+      String successVariableName =
+          JavaUtils.SUCCESS_VARIABLE_PREFIX + "$" + successVariableCount++;
+      String exceptionTempVariableName =
+          JavaUtils.EXCEPTION_VARIABLE_PREFIX + "$" + exceptionVariableCount++;
+      String exceptionVariableName =
+          JavaUtils.EXCEPTION_VARIABLE_PREFIX + "$" + exceptionVariableCount++;
+      buffer.append("boolean ");
+      buffer.append(successVariableName);
+      buffer.append(" = false; ");
+      buffer.append("Throwable ");
+      buffer.append(exceptionVariableName);
+      buffer.append(" = null; ");
+      buffer.append("try { ");
+      buffer.append(successVariableName);
+      buffer.append(" = ");
+      buffer.append(JavaUtils.BEGIN_LOCATION_COMMENT);
+      buffer.append(JavaUtils.quoteComment(exprComment));
+      buffer.append(JavaUtils.END_LOCATION_COMMENT);
+      if (!annotation.isVirtual()) {
+        buffer.append(rebaseLocalCalls(expr, JavaUtils.THAT_VARIABLE, null));
+      } else {
+        buffer.append(expr);
+      }
+      buffer.append("; ");
+      buffer.append("} catch(Throwable ");
+      buffer.append(exceptionTempVariableName);
+      buffer.append(") {");
+      buffer.append(exceptionVariableName);
+      buffer.append(" = ");
+      buffer.append(exceptionTempVariableName);
+      buffer.append("; } ");
+
+      /* Handle failure. */
+      buffer.append("if (!(");
+      buffer.append(successVariableName);
+      buffer.append(")) { ");
+      if (kind.getVariance() == ContractVariance.CONTRAVARIANT) {
+        buffer.append("return new ");
+        buffer.append(trait.getExceptionName());
+        buffer.append("(\"");
+        buffer.append(ContractWriter.quoteString(exprMsg));
+        buffer.append("\", ");
+        buffer.append(JavaUtils.ERROR_VARIABLE);
+        buffer.append(", ");
+        buffer.append(exceptionVariableName);
+        buffer.append("); ");
+      } else {
+        buffer.append(RAISE_METHOD);
+        buffer.append("(new ");
+        buffer.append(trait.getExceptionName());
+        buffer.append("(\"");
+        buffer.append(ContractWriter.quoteString(exprMsg));
+        buffer.append("\", ");
+        buffer.append(exceptionVariableName);
+        buffer.append("));");
+      }
+      buffer.append("} ");
+
+      contract.addStatement(buffer.toString());
+    }
+  }
+
+  /**
+   * Builds a contract method body that calls the specified helper
+   * contract method.
+   */
+  @Requires({
+    "helper != null",
+    "annotation != null"
+  })
+  static String getHelperCallCode(MethodModel helper,
+                                  ContractAnnotationModel annotation) {
+    StringBuilder buffer = new StringBuilder();
+    if (!annotation.isPrimary() && !annotation.isVirtual()) {
+      buffer.append(annotation.getOwner().getQualifiedName()
+                    + JavaUtils.HELPER_CLASS_SUFFIX);
+      buffer.append(".");
+    }
+    buffer.append(helper.getSimpleName());
+    buffer.append("(");
+    List<? extends VariableModel> parameters = helper.getParameters();
+    if (!parameters.isEmpty()) {
+      Iterator<? extends VariableModel> it = parameters.iterator();
+      for (;;) {
+        String name = it.next().getSimpleName();
+        if (name.equals(JavaUtils.THAT_VARIABLE)) {
+          buffer.append("this");
+        } else {
+          buffer.append(name);
+        }
+        if (!it.hasNext()) {
+          break;
+        }
+        buffer.append(", ");
+      }
+    }
+    buffer.append(")");
+    return buffer.toString();
+  }
+
+  static ContractKind getContractKind(ContractAnnotationModel annotation) {
+    switch (annotation.getKind()) {
+      case INVARIANT:
+        return ContractKind.INVARIANT;
+      case REQUIRES:
+        return ContractKind.PRE;
+      case ENSURES:
+        return ContractKind.POST;
+      case THROW_ENSURES:
+        return ContractKind.SIGNAL;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * Visits the specified trait and creates or augment contract and
+   * helper methods as needed.
+   *
+   * @see #createContractMethod(ContractCreationTrait,ContractMethodModel,ContractAnnotationModel,MethodModel)
+   * @see #createContractHelper(ContractCreationTrait,ContractAnnotationModel)
+   */
+  @Requires({
+    "trait != null",
+    "annotation != null"
+  })
+  static ContractMethodModel createContractMethods(
+      ContractCreationTrait trait, ContractMethodModel contract,
+      ContractAnnotationModel annotation) {
+    if (!trait.visit(annotation)) {
+      return null;
+    }
+    MethodModel helper = createContractHelper(trait, annotation);
+    return createContractMethod(trait, contract, annotation, helper);
+  }
+
+  /**
+   * Returns a new blank contract method, according to the annotation
+   * properties, and adds it to the parent type. Such a method returns
+   * {@code void}, and has no code and no line information.
+   *
+   * @param kind the kind of contract method to create
+   * @param annotation the source of the contract
+   * @param nameSuffix a suffix to append to the method name, or
+   * {@code null}
+   * @return the contract method
+   */
+  @Requires({
+    "kind != null",
+    "annotation != null"
+  })
+  @Ensures("result != null")
+  static ContractMethodModel createBlankContractMethod(
+      ContractKind kind, ContractAnnotationModel annotation,
+      String nameSuffix) {
+    TypeModel type = Elements.getTypeOf(annotation);
+
+    MethodModel contracted = null;
+    if (kind.isMethodContract()) {
+      contracted = (MethodModel) annotation.getEnclosingElement();
+    }
+
+    String name = kind.getNameSpace() + getContractName(kind, contracted);
+    if (nameSuffix != null) {
+      name += nameSuffix;
+    }
+    ContractMethodModel contract =
+        new ContractMethodModel(kind, name, new TypeName("void"), contracted);
+
+    contract.addModifier(ElementModifier.PRIVATE);
+    type.addMember(contract);
+
+    return contract;
+  }
+
+  /**
+   * Adds to the specified contract method, or creates a new one and
+   * adds it to the parent type.
+   *
+   * <p>This method does <em>not</em> visit its trait argument.
+   *
+   * @param trait the trait object used to create the contract
+   * @param contract the contract object to be augmented,
+   * or {@code null}
+   * @param annotation the source of the contract
+   * @param helper a helper method to call or {@code null} if this
+   * contract is direct
+   * @return the contract method
+   */
+  @Requires({
+    "trait != null",
+    "annotation != null",
+    "helper != null"
+  })
+  @Ensures("result != null")
+  static ContractMethodModel createContractMethod(
+      ContractCreationTrait trait, ContractMethodModel contract,
+      ContractAnnotationModel annotation, MethodModel helper) {
+    ContractKind kind = getContractKind(annotation);
+
+    if (contract == null) {
+      contract = createBlankContractMethod(kind, annotation, "");
+      Elements.copyParameters(contract, trait.getInitialParameters());
+
+      if (kind.getVariance() == ContractVariance.CONTRAVARIANT) {
+        contract.setPrologue(trait.getExceptionName() + " "
+                             + JavaUtils.ERROR_VARIABLE + " = null;");
+        contract.setEpilogue(RAISE_METHOD + "("
+                             + JavaUtils.ERROR_VARIABLE + ");");
+      }
+    }
+    Elements.copyParameters(contract, trait.getExtraParameters());
+
+    if (annotation.isPrimary()) {
+      contract.setSourceInfo(annotation.getSourceInfo());
+    }
+
+    String code = getHelperCallCode(helper, annotation) + ";";
+    if (kind.getVariance() == ContractVariance.CONTRAVARIANT) {
+      code = JavaUtils.ERROR_VARIABLE + " = " + code
+          + "if (" + JavaUtils.ERROR_VARIABLE + " == null) { return; }";
+    }
+    contract.addStatement(code);
+
+    return contract;
+  }
+
+  /**
+   * Returns a new blank primary or mock helper contract method,
+   * according to the annotation properties, and adds it to the parent
+   * type if needed. Such a method returns {@code void} and has no
+   * code and no line information.
+   *
+   * @param kind the kind of contract method to create
+   * @param annotation the source of the contract
+   * @param nameSuffix a suffix to append to the method name, or
+   * {@code null}
+   */
+  @Requires({
+    "kind != null",
+    "annotation != null"
+  })
+  @Ensures("result != null")
+  static MethodModel createBlankContractHelper(
+      ContractKind kind, ContractAnnotationModel annotation,
+      String nameSuffix) {
+    TypeModel type = Elements.getTypeOf(annotation);
+    MethodModel method = null;
+    ContractMethodModel contract = null;
+
+    MethodModel contracted = null;
+    if (kind.isMethodContract()) {
+      contracted = (MethodModel) annotation.getEnclosingElement();
+    }
+
+    TypeName returnType = new TypeName("void");
+    String name = getHelperName(kind, annotation.getOwner(), contracted);
+    if (nameSuffix != null) {
+      name += nameSuffix;
+    }
+    if (annotation.isPrimary()) {
+      contract = new ContractMethodModel(ContractKind.HELPER, name,
+                                         returnType, contracted);
+
+      contract.setSourceInfo(annotation.getSourceInfo());
+
+      if (!annotation.isVirtual()) {
+        for (TypeName typeParam : type.getTypeParameters()) {
+          contract.addTypeParameter(typeParam);
+        }
+      }
+
+      method = contract;
+    } else {
+      method = new MethodModel(ElementKind.CONTRACT_MOCK, name, returnType);
+      if (contracted != null) {
+        Elements.copyParameters(method, contracted.getParameters());
+      }
+    }
+
+    if (!annotation.isVirtual()) {
+      method.addParameter(
+          new VariableModel(ElementKind.PARAMETER,
+                            JavaUtils.THAT_VARIABLE, annotation.getOwner()));
+    }
+
+    if (!annotation.isVirtual()) {
+      method.addModifier(ElementModifier.PUBLIC);
+      method.addModifier(ElementModifier.STATIC);
+    } else {
+      method.addModifier(ElementModifier.PROTECTED);
+    }
+
+    if (annotation.isPrimary()
+        || annotation.isVirtual() && !annotation.isWeakVirtual()) {
+      type.addMember(method);
+    }
+
+    return method;
+  }
+
+  /**
+   * Creates a new primary or mock helper contract method, according
+   * to the annotation properties, and adds it to the parent type if
+   * needed.
+   *
+   * <p>This method does <em>not</em> visit its trait argument.
+   *
+   * @param trait the trait object used to create the contract
+   * @param annotation the source of the contract
+   */
+  @Requires({
+    "trait != null",
+    "annotation != null"
+  })
+  @Ensures("result != null")
+  static MethodModel createContractHelper(ContractCreationTrait trait,
+                                          ContractAnnotationModel annotation) {
+    ContractKind kind = getContractKind(annotation);
+    MethodModel method = createBlankContractHelper(kind, annotation, null);
+
+    TypeName returnType =
+        new TypeName(kind.getVariance() == ContractVariance.CONTRAVARIANT
+                     ? trait.getExceptionName()
+                     : "void");
+    method.setReturnType(returnType);
+
+    if (kind.getVariance() == ContractVariance.CONTRAVARIANT) {
+      method.addParameter(
+          new VariableModel(ElementKind.PARAMETER,
+                            JavaUtils.ERROR_VARIABLE, returnType));
+    }
+
+    if (annotation.isPrimary()) {
+      method.setSourceInfo(annotation.getSourceInfo());
+    }
+
+    if (method.getKind() == ElementKind.CONTRACT_METHOD) {
+      ContractMethodModel contract = (ContractMethodModel) method;
+
+      Elements.copyParameters(contract, trait.getInitialParameters());
+      Elements.copyParameters(contract, trait.getExtraParameters());
+
+      addContractClauses(contract, trait, annotation);
+      if (kind.getVariance() == ContractVariance.CONTRAVARIANT) {
+        contract.setEpilogue("return null;");
+      }
+
+      if (annotation.isPrimary()) {
+        contract.setLineNumbers(annotation.getLineNumbers());
+      }
+    } else {
+      Elements.copyParameters(method, trait.getInitialMockParameters());
+      Elements.copyParameters(method, trait.getExtraMockParameters());
+    }
+
+    return method;
+  }
+
+  /**
+   * Builds and returns a helper method name.
+   */
+  @Requires({
+    "kind != null",
+    "owner != null"
+  })
+  @Ensures("ClassName.isSimpleName(result)")
+  static String getHelperName(ContractKind kind, ClassName owner,
+                              MethodModel contracted) {
+    return kind.getHelperNameSpace() + "$"
+        + owner.getBinaryName().replace('/', '$')
+        + getContractName(kind, contracted);
+  }
+
+  /**
+   * Returns the relative contract name, without the name space part.
+   */
+  @Requires({
+    "kind != null",
+    "!kind.isClassContract() || contracted == null"
+  })
+  @Ensures({
+    "result.isEmpty() " +
+        "|| ClassName.isSimpleName(result) && result.startsWith(\"$\")"
+  })
+  static String getContractName(ContractKind kind, MethodModel contracted) {
+    if (contracted == null) {
+      return "";
+    } else {
+      if (contracted.isConstructor()) {
+        return "$" + contracted.getEnclosingElement().getSimpleName();
+      } else {
+        return "$" + contracted.getSimpleName();
+      }
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractCreationTrait.java b/src/com/google/java/contract/core/apt/ContractCreationTrait.java
new file mode 100644
index 0000000..47daa81
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractCreationTrait.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.VariableModel;
+
+import java.util.List;
+
+/**
+ * A hybrid visitor with query methods that governs the creation of a
+ * given kind of contract.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at AllowUnusedImport(ClassName.class)
+interface ContractCreationTrait {
+  /**
+   * Called before any of the query methods of this object. Queries
+   * between two calls to this method should be consistent.
+   *
+   * @param annotation the annotation to process
+   * @return {@code true} if there was no error
+   */
+  @Requires("annotation != null")
+  public boolean visit(ContractAnnotationModel annotation);
+
+  /**
+   * Returns the list of expressions to be evaluated by the contract.
+   */
+  @Ensures("result != null")
+  public List<String> getExpressions();
+
+  /**
+   * Returns the list of failure messages associated with the
+   * assertions of the contract.
+   */
+  @Ensures("result != null")
+  public List<String> getMessages();
+
+  /**
+   * Returns the list of expressions to be used in error
+   * reporting. This should be a list of unchanged clauses from the
+   * original annotation.
+   */
+  @Ensures("result != null")
+  public List<String> getSourceExpressions();
+
+  /**
+   * Returns the list of extra parameters to add to the end of the
+   * contract method parameter list. These parameters are only added
+   * at creation; they are <em>not</em> added to an existing contract
+   * method.
+   */
+  @Ensures("result != null")
+  public List<? extends VariableModel> getInitialParameters();
+
+  /**
+   * Returns the list of extra parameters to add to the end of the
+   * contract method parameter list. These parameters are added to the
+   * contract method regardless of whether it is new or not, after
+   * parameters returned by
+   * {@link #getInitialParameters(ContractAnnotationModel)},
+   * if applicable.
+   */
+  @Ensures("result != null")
+  public List<? extends VariableModel> getExtraParameters();
+
+  /**
+   * Returns the list of initial extra parameters for mock
+   * definitions.
+   *
+   * @see getInitialParameters()
+   */
+  @Ensures("result != null")
+  public List<? extends VariableModel> getInitialMockParameters();
+
+  /**
+   * Returns the list of extra parameters for mock definitions.
+   *
+   * @see getExtraParameters()
+   */
+  @Ensures("result != null")
+  public List<? extends VariableModel> getExtraMockParameters();
+
+  /**
+   * Returns the name of the exception type to throw when a failure
+   * occurs.
+   */
+  @Ensures("ClassName.isQualifiedName(result)")
+  public String getExceptionName();
+}
diff --git a/src/com/google/java/contract/core/apt/ContractExpressionCreationTrait.java b/src/com/google/java/contract/core/apt/ContractExpressionCreationTrait.java
new file mode 100644
index 0000000..358c92a
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractExpressionCreationTrait.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+
+import java.util.List;
+
+/**
+ * Creation trait for common transformations shared by all kinds of
+ * contracts.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("transformer != null")
+class ContractExpressionCreationTrait
+    extends SimpleContractCreationTrait {
+  protected ContractExpressionTransformer transformer;
+
+  /**
+   * Constructs a new ContractExpressionTransformer using
+   * {@code transformer}.
+   */
+  @Requires("transformer != null")
+  ContractExpressionCreationTrait(
+      ContractExpressionTransformer transformer) {
+    this.transformer = transformer;
+  }
+
+  /**
+   * Checks and transforms {@code code} through {@link #transformer}.
+   *
+   * @see ContractExpressionTransformer#transform(List<String>,List<Long>,Object)
+   */
+  @Requires({
+    "code != null",
+    "lineNumbers != null",
+    "code.size() == lineNumbers.size()"
+  })
+  protected boolean transform(List<String> code, List<Long> lineNumbers,
+                              Object sourceInfo) {
+    return transformer.transform(code, lineNumbers, sourceInfo);
+  }
+
+  @Override
+  public boolean visit(ContractAnnotationModel annotation) {
+    this.annotation = annotation;
+    return transform(annotation.getValues(), annotation.getLineNumbers(),
+                     annotation.getSourceInfo());
+  }
+
+  @Override
+  public List<String> getExpressions() {
+    return transformer.getTransformedCode();
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractExpressionTransformer.java b/src/com/google/java/contract/core/apt/ContractExpressionTransformer.java
new file mode 100644
index 0000000..e4218c0
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractExpressionTransformer.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.VariableModel;
+import com.google.java.contract.core.util.BalancedTokenizer;
+import com.google.java.contract.core.util.JavaTokenizer.Token;
+import com.google.java.contract.core.util.JavaTokenizer.TokenKind;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A contract expression checker and transformer. An instance of this
+ * class can do basic syntax checking and handle language extensions
+ * supported in contract expression.
+ *
+ * <p>Currently, the following checks are performed:
+ * <ul>
+ * <li>Proper nesting and matching of '()', '[]' and '{}'.
+ * <li>Erroneous ';' in expression.
+ * </ul>
+ *
+ * <p>And the following transformations are applied:
+ * <ul>
+ * <li>Comments are replaced by whitespace.
+ * <li>{@code old()} expressions are extracted and replaced with old
+ * value variable references. (Optional.)
+ * </ul>
+ *
+ * <p>All generated code is marked up with the appropriate tags, as
+ * defined in {@link com.google.java.contract.core.util.JavaUtils}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at Invariant({
+  "diagnosticManager != null",
+  "oldId >= 0",
+  "oldParameters == null || oldParametersCode != null",
+  "oldParameters == null || oldParametersLineNumbers != null",
+  "oldParameters == null || !oldParameters.contains(null)",
+  "oldParameters == null || !oldParametersCode.contains(null)",
+  "oldParameters == null || oldParameters.size() == oldParametersCode.size()",
+  "oldParameters == null " +
+      "|| oldParameters.size() == oldParametersLineNumbers.size()"
+})
+public class ContractExpressionTransformer {
+  private static final String MAGIC_CAST_METHOD =
+      "com.google.java.contract.core.runtime.ContractRuntime.magicCast";
+
+  /**
+   * The diagnostic manager to report errors to.
+   */
+  protected DiagnosticManager diagnosticManager;
+
+  /**
+   * {@code true} if old expressions should be transformed.
+   * If {@code false}, old constructs are ignored.
+   */
+  protected boolean acceptOld;
+
+  /**
+   * The extra parameters needed to hold the extracted old values.
+   */
+  protected List<VariableModel> oldParameters;
+
+  /**
+   * The code corresponding to the old parameters.
+   */
+  protected List<String> oldParametersCode;
+
+  /**
+   * The line numbers corresponding to the old parameters.
+   */
+  protected List<Long> oldParametersLineNumbers;
+
+  /**
+   * The processed code, free of {@code old()} expressions.
+   */
+  protected List<String> newCode;
+
+  /**
+   * Whether the last call to {@link #transform(List<String>,Object)}
+   * was successful.
+   */
+  protected boolean parsed;
+
+  /**
+   * The identifier of the next old variable to allocate.
+   */
+  protected int oldId;
+
+  /**
+   * Constructs a new ContractExpressionTransformer.
+   *
+   * @param diagnosticManager manager to report errors to
+   * @param acceptOld whether old expressions are recognized
+   */
+  public ContractExpressionTransformer(DiagnosticManager diagnosticManager,
+                                       boolean acceptOld) {
+    this.diagnosticManager = diagnosticManager;
+    this.acceptOld = acceptOld;
+    oldParameters = null;
+    oldParametersCode = null;
+    oldParametersLineNumbers = null;
+    newCode = null;
+    parsed = false;
+    oldId = 0;
+  }
+
+  public void setAcceptOld(boolean acceptOld) {
+    this.acceptOld = acceptOld;
+  }
+
+  @Requires({
+    "currentBuffer != null",
+    "tokenizer != null",
+    "token != null"
+  })
+  private void transformCommon(StringBuilder currentBuffer,
+                              BalancedTokenizer tokenizer, Token token) {
+    switch (token.kind) {
+      case COMMENT:
+        int length = token.text.length();
+        for (int i = 0; i < length; ++i) {
+          currentBuffer.append(" ");
+        }
+        break;
+      default:
+        currentBuffer.append(token.text);
+    }
+  }
+
+  /**
+   * Checks and transforms {@code code}. If successful, results are
+   * stored in this instance and can be queried using the appropriate
+   * methods.
+   *
+   * @param code the list of contract expressions to parse
+   * @param lineNumbers line numbers associated with {@code code}
+   * @param sourceInfo optional source information
+   * @return {@code true} if there was no errors
+   */
+  @Requires({
+    "code != null",
+    "lineNumbers != null",
+    "code.size() == lineNumbers.size()"
+  })
+  @Ensures({
+    "result == canQueryResults()",
+    "!result || newCode.size() == code.size()"
+  })
+  @SuppressWarnings("fallthrough")
+  public boolean transform(List<String> code, List<Long> lineNumbers,
+                           Object sourceInfo) {
+    oldParameters = new ArrayList<VariableModel>();
+    oldParametersCode = new ArrayList<String>();
+    oldParametersLineNumbers = new ArrayList<Long>();
+    newCode = new ArrayList<String>();
+    parsed = true;
+
+    Iterator<Long> iterLineNumber = lineNumbers.iterator();
+
+   code:
+    for (String expr : code) {
+      Long lineNumber = iterLineNumber.hasNext() ? iterLineNumber.next() : null;
+
+      BalancedTokenizer tokenizer =
+          new BalancedTokenizer(new StringReader(expr));
+      int currentLevel = 0;
+      int newLevel = 0;
+
+      StringBuilder buffer = new StringBuilder();
+
+      StringBuilder oldBuffer = null;
+      String oldName = null;
+      int oldContext = -1;
+
+      while (tokenizer.hasNext()) {
+        Token token = tokenizer.next();
+        newLevel = tokenizer.getCurrentLevel();
+
+        StringBuilder currentBuffer = oldBuffer != null ? oldBuffer : buffer;
+
+        /* Unexpected ';' error. */
+        if (newLevel == 0 && token.text.equals(";")) {
+          diagnosticManager.error("'\"' expected",
+              expr, token.offset, token.offset, token.offset,
+              sourceInfo);
+          parsed = false;
+          continue code;
+        }
+
+        /* old expressions. */
+        if (oldBuffer != null) {
+          if (newLevel == oldContext) {
+            /* End of old expression. */
+            String oldExpr = oldBuffer.toString();
+            oldParameters.add(
+                new VariableModel(ElementKind.PARAMETER, oldName,
+                                  new ClassName("java/lang/Object")));
+            oldParametersCode.add(oldExpr);
+            oldParametersLineNumbers.add(lineNumber);
+
+            /* Pad buffer (for error reporting purposes). */
+            buffer.append("(   ");
+
+            /* Replace old expression in original expression. */
+            buffer.append(JavaUtils.BEGIN_GENERATED_CODE);
+            buffer.append(MAGIC_CAST_METHOD);
+            buffer.append("(");
+            buffer.append(oldName);
+            buffer.append(", ");
+            buffer.append("true ? null : ");
+            buffer.append(JavaUtils.END_GENERATED_CODE);
+            buffer.append(oldExpr);
+            buffer.append(JavaUtils.BEGIN_GENERATED_CODE);
+            buffer.append(")");
+            buffer.append(JavaUtils.END_GENERATED_CODE);
+
+            /* Pad buffer (for error reporting purposes). */
+            buffer.append(")");
+
+            /* Exit old context. */
+            oldBuffer = null;
+            oldContext = -1;
+          } else {
+            switch (token.kind) {
+              case WORD:
+                if (token.text.equals("old")) {
+                  diagnosticManager.error("nested old expression",
+                      expr, token.offset, token.offset, token.offset,
+                      sourceInfo);
+                  parsed = false;
+                  continue code;
+                }
+                oldBuffer.append(token.text);
+                break;
+              default:
+                transformCommon(oldBuffer, tokenizer, token);
+            }
+          }
+        } else {
+          switch (token.kind) {
+            case WORD:
+              if (acceptOld && token.text.equals("old")) {
+                /* Start of old expression. */
+                Token afterOld = null;
+                if (!tokenizer.hasNext()
+                    || !((afterOld = tokenizer.next()).text.equals("(")
+                         || (afterOld.kind == TokenKind.SPACE
+                             && tokenizer.hasNext()
+                             && tokenizer.next().text.equals("(")))) {
+                  int errorPos = afterOld != null ? afterOld.offset
+                      : tokenizer.getCurrentOffset();
+                  diagnosticManager.error("'(' expected",
+                      expr, errorPos, errorPos, errorPos,
+                      sourceInfo);
+                  parsed = false;
+                  continue code;
+                }
+
+                /* Compute new old variable name. */
+                oldName = JavaUtils.OLD_VARIABLE_PREFIX + oldId++;
+
+                /* Enter old context. */
+                if (afterOld.kind == TokenKind.SPACE) {
+                  oldBuffer = new StringBuilder(afterOld.text);
+                } else {
+                  oldBuffer = new StringBuilder();
+                }
+                oldContext = currentLevel;
+                break;
+              }
+              /* Fall through. */
+            default:
+              transformCommon(buffer, tokenizer, token);
+          }
+        }
+
+        currentLevel = newLevel;
+      }
+
+      /* Parse errors. */
+      if (tokenizer.hasErrors()) {
+        int errorPos = tokenizer.getCurrentOffset();
+        diagnosticManager.error(tokenizer.getErrorMessage(),
+            expr, errorPos, errorPos, errorPos, sourceInfo);
+        parsed = false;
+        continue code;
+      }
+      newCode.add(buffer.toString());
+    }
+
+    return parsed;
+  }
+
+  /**
+   * Returns {@code true} if results are ready to be queried.
+   */
+  public boolean canQueryResults() {
+    return parsed;
+  }
+
+  @Ensures("result >= 0")
+  public int getNextOldId() {
+    return oldId;
+  }
+
+  @Requires("canQueryResults()")
+  @Ensures({
+    "result != null",
+    "result.size() == getOldParametersCode().size()",
+    "result.size() == getOldParametersLineNumbers().size()"
+  })
+  public List<VariableModel> getOldParameters() {
+    return oldParameters;
+  }
+
+  @Requires("canQueryResults()")
+  @Ensures({
+    "result != null",
+    "result.size() == getOldParameters().size()",
+    "result.size() == getOldParametersLineNumbers().size()"
+  })
+  public List<String> getOldParametersCode() {
+    return oldParametersCode;
+  }
+
+  @Requires("canQueryResults()")
+  @Ensures({
+    "result != null",
+    "result.size() == getOldParameters().size()",
+    "result.size() == getOldParametersCode().size()"
+  })
+  public List<Long> getOldParametersLineNumbers() {
+    return oldParametersLineNumbers;
+  }
+
+  @Requires("canQueryResults()")
+  @Ensures("result != null")
+  public List<String> getTransformedCode() {
+    return newCode;
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractFinder.java b/src/com/google/java/contract/core/apt/ContractFinder.java
new file mode 100644
index 0000000..a352515
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractFinder.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.runtime.BlacklistManager;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementScanner6;
+
+/**
+ * Recursively scans the type tree looking for contract annotations. Results
+ * are cached so there's no need to scan the same element twice.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at Invariant("this.contractedElements != null")
+public class ContractFinder
+    extends ElementScanner6<Boolean, Void> {
+  private FactoryUtils utils;
+  private Map<TypeElement, Boolean> contractedElements;
+  private BlacklistManager blackList;
+
+  @Requires("utils != null")
+  public ContractFinder(FactoryUtils utils) {
+    this.utils = utils;
+    this.contractedElements = new HashMap<TypeElement, Boolean>();
+    this.blackList = BlacklistManager.getInstance();
+  }
+
+  @Override
+  @Ensures("result != null")
+  public Boolean visitType(TypeElement e, Void v) {
+    /* The current element has already been analyzed. */
+    if (contractedElements.containsKey(e)) {
+      return contractedElements.get(e);
+    }
+
+    /* The element is in the blacklist, do not scan. */
+    if (blackList.isIgnored(e.getQualifiedName().toString())) {
+      contractedElements.put(e, Boolean.FALSE);
+      return Boolean.FALSE;
+    }
+
+    /*
+     * Before searching for contracts, add the element to the visited cache.
+     * This is important to avoid recursion (e.g. when an enclosed element
+     * extends the enclosing one).
+     */
+    contractedElements.put(e, Boolean.FALSE);
+    Boolean contracted = isContractedType(e);
+    contractedElements.put(e, contracted);
+    return contracted;
+  }
+
+  @Override
+  @Ensures("result != null")
+  public Boolean visitExecutable(ExecutableElement e, Void p) {
+    return hasContracts(e.getAnnotationMirrors());
+  }
+
+  @Override
+  @Ensures("result != null")
+  public Boolean visitVariable(VariableElement e, Void p) {
+    /* Variables do not have contracts. */
+    return Boolean.FALSE;
+  }
+
+  @Override
+  @Ensures("result != null")
+  public Boolean visitPackage(PackageElement e, Void p) {
+    /* Packages do not have contracts. */
+    return Boolean.FALSE;
+  }
+
+  @Override
+  @Ensures("result != null")
+  public Boolean visitTypeParameter(TypeParameterElement e, Void p) {
+    /* Type parameters do not have contracts. */
+    return Boolean.FALSE;
+  }
+
+  /**
+   * Scans a {@code TypeElement} looking for contracts.
+   * If contracts are not found on the type itself, scans its enclosed elements,
+   * implemented interfaces and superclass.
+   *
+   * @param e the element to be scanned
+   * @return whether the element contains contracts
+   */
+  @Requires("e != null")
+  @Ensures("result != null")
+  private Boolean isContractedType(TypeElement e) {
+    Boolean result = Boolean.FALSE;
+
+    /* The current element has contracts on its annotations. */
+    result = hasContracts(e.getAnnotationMirrors());
+
+    /* Checks superclass. */
+    if (!result) {
+      Element superclass =
+          utils.typeUtils.asElement(e.getSuperclass());
+      if (superclass != null) {
+        /* Scans up in the syntax tree looking for contract annotations. */
+        result = superclass.accept(this, null);
+      }
+    }
+
+    /* Checks interfaces. */
+    if (!result) {
+      Collection<? extends TypeMirror> interfaces = e.getInterfaces();
+      for (TypeMirror i : interfaces) {
+        Element iface = utils.typeUtils.asElement(i);
+        result = iface.accept(this, null);
+        if (result) {
+          break;
+        }
+      }
+    }
+
+    /* Scan the enclosed elements of this. */
+    if (!result) {
+      List<? extends Element> enclosed = e.getEnclosedElements();
+      for (Element element : enclosed) {
+        result = element.accept(this, null);
+        if (result) {
+          break;
+        }
+      }
+    }
+
+    return result;
+  }
+
+  @Requires("annotations != null")
+  @Ensures("result != null")
+  private Boolean hasContracts(
+      Collection<? extends AnnotationMirror> annotations) {
+    for (AnnotationMirror a : annotations) {
+      if (utils.isContractAnnotation(a)) {
+        return Boolean.TRUE;
+      }
+    }
+    return Boolean.FALSE;
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractJavaCompiler.java b/src/com/google/java/contract/core/apt/ContractJavaCompiler.java
new file mode 100644
index 0000000..c9b26b6
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractJavaCompiler.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * A compiler that handles generated contract source files.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+ at Invariant({
+  "javaCompiler != null",
+  "fileManager != null"
+})
+public class ContractJavaCompiler {
+  /**
+   * The compiler options passed to the internal compiler.
+   */
+  protected static final List<String> OPTIONS =
+      Arrays.asList(
+          "-g:source,vars", /* Source file name, for debug attributes. */
+          "-proc:none",     /* No further annotations to process. */
+          "-implicit:none"  /* No class files for implicit dependencies. */
+      );
+
+  /**
+   * Internal compiler to delegate to.
+   */
+  protected JavaCompiler javaCompiler;
+
+  protected ContractJavaFileManager fileManager;
+
+  public ContractJavaCompiler(String sourcePath, String classPath,
+                              String outputDirectory)
+      throws IOException {
+    javaCompiler = ToolProvider.getSystemJavaCompiler();
+    if (javaCompiler == null) {
+      throw new IOException("no system JavaCompiler found; "
+                            + "are you using a JRE instead of a JDK?");
+    }
+
+    fileManager = new ContractJavaFileManager(
+        javaCompiler.getStandardFileManager(null, null, null));
+
+    if (sourcePath != null) {
+      setPath(StandardLocation.SOURCE_PATH, sourcePath);
+    }
+    if (classPath != null) {
+      setPath(StandardLocation.CLASS_PATH, classPath);
+    }
+    if (outputDirectory != null) {
+      setClassOutputDirectory(outputDirectory);
+    }
+  }
+
+  /**
+   * Returns a new compilation task.
+   */
+  @Requires({
+    "files != null",
+    "diagnostics != null"
+  })
+  @Ensures("result != null")
+  public CompilationTask getTask(List<? extends JavaFileObject> files,
+      DiagnosticListener<JavaFileObject> diagnostics) {
+    return javaCompiler.getTask(null, fileManager, diagnostics,
+                                OPTIONS, null, files);
+  }
+
+  @Requires({
+    "location != null",
+    "path != null"
+  })
+  protected void setPath(Location location, String path) throws IOException {
+    String[] parts = path.split(Pattern.quote(File.pathSeparator));
+    ArrayList<File> dirs = new ArrayList<File>(parts.length);
+    for (String part : parts) {
+      dirs.add(new File(part));
+    }
+    fileManager.setLocation(location, dirs);
+  }
+
+  @Requires("outputDirectory != null")
+  protected void setClassOutputDirectory(String outputDirectory)
+      throws IOException {
+    fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
+        Collections.singletonList(new File(outputDirectory)));
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractJavaFileManager.java b/src/com/google/java/contract/core/apt/ContractJavaFileManager.java
new file mode 100644
index 0000000..0d4ab4d
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractJavaFileManager.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.util.Elements;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+/**
+ * A file manager that handles output (class) files from contract
+ * compilation. Class files are written in the configured class output
+ * directory (usually alongside other class files).
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+public class ContractJavaFileManager
+    extends ForwardingJavaFileManager<StandardJavaFileManager> {
+  /**
+   * An output file to a plain contract class file.
+   */
+  @Invariant("file != null")
+  protected class SimpleOutputJavaFileObject extends SimpleJavaFileObject {
+    protected FileObject file;
+
+    @Requires({
+      "binaryName != null",
+      "file != null"
+    })
+    public SimpleOutputJavaFileObject(String binaryName, FileObject file) {
+      super(Elements.getUriForClass(binaryName, Kind.CLASS), Kind.CLASS);
+      this.file = file;
+    }
+
+    @Override
+    public OutputStream openOutputStream() throws IOException {
+      return file.openOutputStream();
+    }
+  }
+
+  /**
+   * Constructs a new ContractJavaFileManager writing files to
+   * {@code fileManager}.
+   */
+  @Requires("fileManager != null")
+  public ContractJavaFileManager(StandardJavaFileManager fileManager) {
+    super(fileManager);
+  }
+
+  @Override
+  public JavaFileObject getJavaFileForOutput(Location location,
+      String className, Kind kind, FileObject sibling)
+      throws IOException {
+    String binaryName = className.replace('.', '/');
+    String relativeName = ClassName.getRelativeName(className);
+    if (relativeName.endsWith(JavaUtils.HELPER_CLASS_SUFFIX)) {
+      relativeName += Kind.CLASS.extension;
+    } else {
+      relativeName += JavaUtils.CONTRACTS_EXTENSION;
+    }
+    FileObject file =
+        fileManager.getFileForOutput(location,
+                                     ClassName.getPackageName(className),
+                                     relativeName, sibling);
+    return new SimpleOutputJavaFileObject(binaryName, file);
+  }
+
+  /**
+   * Returns a list of paths associated with {@code location}, or
+   * {@code null}.
+   */
+  @Requires("location != null")
+  public List<? extends File> getLocation(Location location) {
+    Iterable<? extends File> path = fileManager.getLocation(location);
+    if (path == null) {
+      return null;
+    }
+
+    ArrayList<File> locations = new ArrayList<File>();
+    for (File entry : path) {
+      locations.add(entry);
+    }
+    return locations;
+  }
+
+  /**
+   * Sets the list of paths associated with {@code location}.
+   *
+   * @param location the affected location
+   * @param path a list of paths, or {@code null} to reset to default
+   */
+  @Requires("location != null")
+  public void setLocation(Location location, List<? extends File> path)
+      throws IOException {
+    fileManager.setLocation(location, path);
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/ContractWriter.java b/src/com/google/java/contract/core/apt/ContractWriter.java
new file mode 100644
index 0000000..80a5d36
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/ContractWriter.java
@@ -0,0 +1,629 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.core.model.ContractMethodModel;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModifier;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.TypeName;
+import com.google.java.contract.core.model.VariableModel;
+import com.google.java.contract.core.util.ElementScanner;
+import com.google.java.contract.core.util.Elements;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * An element visitor that writes the contract Java source associated
+ * with a given {@link Type} as Java source code to an output stream.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at AllowUnusedImport({ Iterables.class, Predicates.class })
+ at Invariant({
+  "getLineNumberMap() != null",
+  "Iterables.all(getLineNumberMap().keySet(), Predicates.between(1L, null))",
+  "output != null",
+  "lineNumber >= 1"
+})
+public class ContractWriter extends ElementScanner {
+  private static final List<String> numericTypes =
+      Arrays.asList("char", "byte", "short", "int", "long", "float", "double");
+
+  private static final String CONTRACT_METHOD_SIGNATURE =
+      "com.google.java.contract.core.agent.ContractMethodSignature";
+  private static final String CONTRACT_KIND =
+      "com.google.java.contract.core.model.ContractKind";
+
+  private static final Pattern VARIADIC_REGEX =
+      Pattern.compile("\\[\\p{javaWhitespace}*\\]\\p{javaWhitespace}*$");
+
+  protected boolean debugTrace;
+
+  protected ByteArrayOutputStream output;
+
+  protected long lineNumber;
+
+  /**
+   * The resulting mapping between contract annotations and generated
+   * line numbers.
+   */
+  protected Map<Long, Object> lineNumberMap;
+
+  /**
+   * {@code true} if this visitor is currently visiting the root
+   * (top-level) class definition.
+   */
+  protected boolean isRootClass;
+
+  protected TypeModel type;
+
+  protected ContractWriter() {
+    this(false);
+  }
+
+  protected ContractWriter(boolean debugTrace) {
+    this.debugTrace = debugTrace;
+    output = new ByteArrayOutputStream();
+    lineNumber = 1;
+    lineNumberMap = new HashMap<Long, Object>();
+    isRootClass = true;
+    type = null;
+  }
+
+  @Requires("parent != null")
+  protected ContractWriter(ContractWriter parent) {
+    debugTrace = parent.debugTrace;
+    output = parent.output;
+    lineNumber = parent.lineNumber;
+    lineNumberMap = parent.lineNumberMap;
+    isRootClass = false;
+    type = null;
+  }
+
+  /**
+   * Returns a default value string of the specified type.
+   */
+  @Requires("type != null")
+  @Ensures("result != null")
+  protected static String getDefaultValue(TypeName type) {
+    String name = type.getDeclaredName();
+    if (name.equals("boolean")) {
+      return "false";
+    } else if (numericTypes.contains(name)) {
+      return "(" + name + ")0";
+    } else {
+      return "(" + name + ")null";
+    }
+  }
+
+  @Requires("str != null")
+  protected void append(String str) {
+    try {
+      output.write(str.getBytes());
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Ensures("lineNumber == old(lineNumber) + 1")
+  protected void appendEndOfLine() {
+    output.write('\n');
+    ++lineNumber;
+  }
+
+  @Requires("info != null")
+  @Ensures("lineNumber == old(lineNumber) + 1")
+  protected void appendEndOfLine(Object info) {
+    lineNumberMap.put(lineNumber, info);
+    appendEndOfLine();
+  }
+
+  @Requires({
+    "list != null",
+    "separator != null"
+  })
+  private void appendJoin(Collection<?> list, String separator) {
+    if (list.isEmpty()) {
+      return;
+    }
+
+    Iterator<?> it = list.iterator();
+    for (;;) {
+      append(it.next().toString());
+      if (!it.hasNext()) {
+        break;
+      }
+      append(separator);
+    }
+  }
+
+  @Requires("signature != null")
+  private void appendGenericSignature(List<? extends TypeName> signature) {
+    if (!signature.isEmpty()) {
+      append("<");
+      appendJoin(signature, ", ");
+      append(">");
+    }
+  }
+
+  @Requires("modifiers != null")
+  private void appendModifiers(EnumSet<ElementModifier> modifiers) {
+    List<ElementModifier> list = new ArrayList<ElementModifier>(modifiers);
+    Collections.sort(list);
+    appendJoin(list, " ");
+  }
+
+  @Requires("rootType != null")
+  private void appendPackageDeclaration(TypeModel rootType) {
+    String packageName =
+        ClassName.getPackageName(rootType.getName().getSemiQualifiedName());
+    if (!packageName.isEmpty()) {
+      append("package ");
+      append(packageName);
+      append(";");
+      appendEndOfLine();
+    }
+  }
+
+  @Requires({
+    "rootType != null",
+    "rootType.getEnclosingElement() == null"
+  })
+  private void appendImportStatements(TypeModel rootType) {
+    for (String importName : rootType.getImportNames()) {
+      append("import ");
+      append(importName);
+      append(";");
+      appendEndOfLine();
+    }
+  }
+
+  @Requires("variable != null")
+  private void appendVariableDeclaration(VariableModel variable) {
+    appendVariableDeclaration(variable, null);
+  }
+
+  @Requires("variable != null")
+  private void appendVariableDeclaration(VariableModel variable,
+                                         String typeNameOverride) {
+    appendModifiers(variable.getModifiers());
+    append(" ");
+    if (typeNameOverride == null) {
+      append(variable.getType().getDeclaredName());
+    } else {
+      append(typeNameOverride);
+    }
+    append(" ");
+    append(variable.getSimpleName());
+  }
+
+  @Requires("method != null")
+  private void appendMethodDeclaration(MethodModel method) {
+    EnumSet<ElementModifier> modifiers = method.getModifiers();
+    if (type.getKind().isInterfaceType()) {
+      modifiers.remove(ElementModifier.ABSTRACT);
+    }
+    appendModifiers(modifiers);
+    append(" ");
+    appendGenericSignature(method.getTypeParameters());
+
+    if (method.isConstructor()) {
+      append(" ");
+      append(method.getEnclosingElement().getSimpleName());
+    } else {
+      append(" ");
+      append(method.getReturnType().getDeclaredName());
+      append(" ");
+      append(method.getSimpleName());
+    }
+
+    append("(");
+    Iterator<? extends VariableModel> it = method.getParameters().iterator();
+    if (it.hasNext()) {
+      VariableModel param = it.next();
+      while (it.hasNext()) {
+        appendVariableDeclaration(param);
+        append(", ");
+        param = it.next();
+      }
+      if (!method.isVariadic()) {
+        appendVariableDeclaration(param);
+      } else {
+        String variadicTypeName =
+            VARIADIC_REGEX.matcher(param.getType().getDeclaredName())
+            .replaceFirst("...");
+        appendVariableDeclaration(param, variadicTypeName);
+      }
+    }
+    append(")");
+
+    Set<? extends TypeName> exceptions = method.getExceptions();
+    if (exceptions.size() != 0) {
+      append(" throws ");
+      appendJoin(exceptions, ", ");
+    }
+  }
+
+  @Requires({
+    "method != null",
+    "method.isConstructor()"
+  })
+  private void appendConstructorCode(MethodModel method) {
+    TypeModel parent = Elements.getTypeOf(method);
+    List<? extends TypeName> superArguments = parent.getSuperArguments();
+    if (!superArguments.isEmpty()) {
+      append("super(");
+      Iterator<? extends TypeName> it = superArguments.iterator();
+      for (;;) {
+        append(getDefaultValue(it.next()));
+        if (!it.hasNext()) {
+          break;
+        }
+        append(", ");
+      }
+      append(");");
+    }
+  }
+
+  @Requires({
+    "method != null",
+    "!method.isConstructor()"
+  })
+  private void appendNormalMethodCode(MethodModel method) {
+    TypeName returnType = method.getReturnType();
+    if (!returnType.getDeclaredName().equals("void")) {
+      append("return ");
+      append(getDefaultValue(returnType));
+      append(";");
+    }
+  }
+
+  @Requires("contract != null")
+  private void appendContractSignature(ContractMethodModel contract) {
+    append("@");
+    append(CONTRACT_METHOD_SIGNATURE);
+    append("(");
+
+    append("kind = ");
+    append(CONTRACT_KIND);
+    append(".");
+    append(contract.getContractKind().name());
+
+    int id = contract.getId();
+    if (id != -1) {
+      append(", id = ");
+      append(Integer.toString(id));
+    }
+
+    MethodModel contracted = contract.getContractedMethod();
+    if (contracted != null) {
+      append(", target = \"");
+      append(contracted.getSimpleName());
+      append("\"");
+    }
+
+    List<Long> lineNumbers = contract.getLineNumbers();
+    if (lineNumbers != null && !lineNumbers.isEmpty()) {
+      append(", lines = { ");
+      Iterator<Long> it = lineNumbers.iterator();
+      for (;;) {
+        Long lineNumber = it.next();
+        append(Long.toString(lineNumber == null ? -1 : lineNumber));
+        if (!it.hasNext()) {
+          break;
+        }
+        append(", ");
+      }
+      append(" }");
+    }
+
+    append(")");
+    appendEndOfLine();
+  }
+
+  @Override
+  public void visitVariable(VariableModel variable) {
+    if (variable.getKind() == ElementKind.CONSTANT) {
+      /* Handled in visitType(). */
+      return;
+    }
+
+    appendVariableDeclaration(variable);
+    if (variable.getModifiers().contains(ElementModifier.FINAL)) {
+      append(" = ");
+      String defaultValue = getDefaultValue(variable.getType());
+      /*
+       * Append dummy check to prevent the compiler from substituting the field
+       * for its value on contract-checking methods.
+       */
+      append("\"dummy\".equals(\"dummy\") ? ");
+      append(defaultValue);
+      append(":");
+      append(defaultValue);
+    }
+    append(";");
+    appendEndOfLine();
+  }
+
+  @Override
+  public void visitContractMethod(ContractMethodModel contract) {
+    appendContractSignature(contract);
+    appendMethodDeclaration(contract);
+    append(" {");
+    appendEndOfLine();
+
+    Object info = contract.getSourceInfo();
+    if (debugTrace && contract.getContractKind() == ContractKind.HELPER) {
+      append("com.google.java.contract.core.util.DebugUtils.contractInfo(");
+      append("\"checking contract: ");
+      append(quoteString(((TypeModel) contract.getEnclosingElement())
+                         .getName().getQualifiedName()));
+      append(".");
+      append(quoteString(contract.getSimpleName()));
+      if (info instanceof AnnotationSourceInfo) {
+        AnnotationSourceInfo sourceInfo = (AnnotationSourceInfo) info;
+        append(": ");
+        append(quoteString(sourceInfo.getAnnotationValue().toString()));
+      }
+      append("\");");
+      appendEndOfLine();
+    }
+    append(contract.getCode());
+    if (info == null) {
+      appendEndOfLine();
+    } else {
+      appendEndOfLine(info);
+    }
+
+    append("}");
+    appendEndOfLine();
+  }
+
+  @Override
+  public void visitMethod(MethodModel method) {
+    /* Enum constructors are handled in visitType(). */
+    if (type.getKind() == ElementKind.ENUM
+        && method.getSimpleName().equals("<init>")) {
+      return;
+    }
+
+    appendMethodDeclaration(method);
+    if (type.getKind().isInterfaceType()
+        || method.getModifiers().contains(ElementModifier.ABSTRACT)) {
+      append(";");
+    } else {
+      append(" {");
+      appendEndOfLine();
+      if (method.isConstructor()) {
+        appendConstructorCode(method);
+      } else {
+        appendNormalMethodCode(method);
+      }
+      appendEndOfLine();
+      append("}");
+    }
+    appendEndOfLine();
+  }
+
+  @Override
+  public void visitType(TypeModel type) {
+    if (this.type != null) {
+      ContractWriter subwriter = new ContractWriter(this);
+      subwriter.visitType(type);
+      lineNumber = subwriter.lineNumber;
+      return;
+    }
+    this.type = type;
+
+    /* Package. */
+    if (isRootClass) {
+      appendPackageDeclaration(type);
+      appendImportStatements(type);
+    }
+
+    /* Type and name. */
+    appendTypeDeclaration(type);
+
+    /* Superclass. */
+    appendSuperclass(type);
+
+    /* Interfaces. */
+    appendInterfaces(type);
+
+    /* Body. */
+    append(" {");
+    appendEndOfLine();
+
+    if (type.getKind() == ElementKind.ENUM) {
+      appendEnumSkeleton(type);
+    }
+
+    /* Members. */
+    scan(type.getEnclosedElements());
+
+    /* End of type. */
+    append("}");
+    appendEndOfLine();
+  }
+
+  @Requires("kind != null")
+  private String getKeywordForType(ElementKind kind) {
+    String keyword = null;
+    switch (type.getKind()) {
+      case CLASS:
+        keyword = "class";
+        break;
+      case ENUM:
+        keyword = "enum";
+        break;
+      case INTERFACE:
+        keyword = "interface";
+        break;
+      case ANNOTATION_TYPE:
+        keyword = "@interface";
+        break;
+    }
+    return keyword;
+  }
+
+  /**
+   * Adds enum constants and a dummy constructor.
+   */
+  @Requires("type != null")
+  private void appendEnumSkeleton(TypeModel type) {
+    /* Enum constants. */
+    List<? extends VariableModel> constants =
+        Elements.filter(type.getEnclosedElements(), VariableModel.class,
+                        ElementKind.CONSTANT);
+    Iterator<? extends VariableModel> it = constants.iterator();
+    if (it.hasNext()) {
+      for (;;) {
+        append(it.next().getSimpleName());
+        if (!it.hasNext()) {
+          break;
+        }
+        append(", ");
+      }
+    }
+    append(";");
+    appendEndOfLine();
+
+    /* Enum dummy constructor. */
+    append("private ");
+    append(type.getSimpleName());
+    append("() {");
+    appendEndOfLine();
+    append("}");
+    appendEndOfLine();
+  }
+
+  /**
+   * Adds the type declaration information, including modifiers, name and
+   * generic signature.
+   */
+  private void appendTypeDeclaration(TypeModel type) {
+    String keyword = getKeywordForType(type.getKind());
+    if (keyword == null)
+      throw new IllegalArgumentException();
+
+    /* Type modifiers. */
+    EnumSet<ElementModifier> modifiers = type.getModifiers();
+    switch(type.getKind()) {
+      case INTERFACE:
+        modifiers.remove(ElementModifier.ABSTRACT);
+        break;
+      case ANNOTATION_TYPE:
+        modifiers.remove(ElementModifier.ABSTRACT);
+        modifiers.remove(ElementModifier.STATIC);
+        break;
+    }
+
+    appendModifiers(modifiers);
+    append(" ");
+    append(keyword);
+    append(" ");
+
+    /* Type name. */
+    String printName = type.getSimpleName();
+    append(printName);
+
+    /* Generic parameters. */
+    appendGenericSignature(type.getTypeParameters());
+  }
+
+  /**
+   * Adds superclass information if needed.
+   */
+  @Requires("type != null")
+  private void appendSuperclass(TypeModel type) {
+    if (type.getKind() != ElementKind.ENUM
+        && type.getSuperclass() != null) {
+      append(" extends ");
+      append(type.getSuperclass().getDeclaredName());
+    }
+  }
+
+  /**
+   * Appends information about the interfaces implemented by this type.
+   * All annotations implicitly implement
+   * {@code java.lang.annotation.Annotation}, but this can't be explicitly
+   * declared on the mock.
+   */
+  @Requires({
+    "type != null",
+    "type.getKind() != ElementKind.ANNOTATION_TYPE" +
+        "|| type.getInterfaces().size() == 1"
+  })
+  private void appendInterfaces(TypeModel type) {
+    final ElementKind kind = type.getKind();
+    if (kind != ElementKind.ANNOTATION_TYPE) {
+      Set<? extends ClassName> interfaces = type.getInterfaces();
+      if (interfaces.size() != 0) {
+        if (kind == ElementKind.INTERFACE) {
+          append(" extends ");
+        } else {
+          append(" implements ");
+        }
+        appendJoin(interfaces, ", ");
+      }
+    }
+  }
+
+  /**
+   * Backslash-quotes the specified string for inclusion in source
+   * code.
+   */
+  @Requires("s != null")
+  @Ensures("result != null")
+  public static String quoteString(String s) {
+    return s.replace("\\", "\\\\").replace("\"", "\\\"");
+  }
+
+  public Map<Long, ?> getLineNumberMap() {
+    return lineNumberMap;
+  }
+
+  @Ensures("result != null")
+  public byte[] toByteArray() {
+    return output.toByteArray();
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/DiagnosticManager.java b/src/com/google/java/contract/core/apt/DiagnosticManager.java
new file mode 100644
index 0000000..2899b22
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/DiagnosticManager.java
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2010, 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.JavaUtils;
+import com.google.java.contract.core.util.SyntheticJavaFile;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileObject;
+
+/**
+ * A collection of diagnostic messages with facilities to manage
+ * messaging and error reporting.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class DiagnosticManager
+    implements DiagnosticListener<JavaFileObject>,
+        Iterable<DiagnosticManager.Report> {
+  /**
+   * An object that can represent heterogeneous kinds of diagnostics,
+   * with query methods suitable for use with
+   * {@link javax.annotation.processing.Messager}.
+   *
+   * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+   */
+  @Invariant({
+    "getKind() != null",
+    "getMessage(null) != null",
+    "getAnnotationMirror() == null || getElement() != null",
+    "getAnnotationValue() == null || getAnnotationMirror() != null"
+  })
+  public abstract class Report {
+    /**
+     * Returns the kind of this diagnostic.
+     */
+    public abstract Kind getKind();
+
+    /**
+     * Returns a error message localized according to {@code locale},
+     * or the default locale if {@code null}.
+     */
+    public abstract String getMessage(Locale locale);
+
+    /**
+     * Returns the Java annotation processing model element
+     * associated with this diagnostic, if any.
+     */
+    public abstract Element getElement();
+
+    /**
+     * Returns the Java annotation processing model annotation mirror
+     * associated with this diagnostic, if any.
+     */
+    public abstract AnnotationMirror getAnnotationMirror();
+
+    /**
+     * Returns the Java annotation processing model annotation value
+     * associated with this diagnostic.
+     */
+    public abstract AnnotationValue getAnnotationValue();
+
+    /**
+     * Appends to {@code buffer} a string with the faulty part
+     * underlined.
+     */
+    @Requires({
+      "buffer != null",
+      "expr != null",
+      "pos >= start",
+      "pos <= end",
+      "start >= 0",
+      "start <= end",
+      "end <= expr.length()"
+    })
+    protected void underlineError(StringBuilder buffer, String expr,
+                                  int pos, int start, int end) {
+      int i = 0;
+      for (; i < start; ++i) {
+        buffer.append(" ");
+      }
+
+      if (pos == start) {
+        buffer.append("^");
+      } else {
+        for (; i < pos; ++i) {
+          buffer.append("~");
+        }
+        buffer.append("^");
+        ++i;
+        for (; i < end; ++i) {
+          buffer.append("~");
+        }
+      }
+    }
+  }
+
+  /**
+   * A diagnostic fired by the annotation processor or one of its
+   * components.
+   *
+   * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+   */
+  public class AnnotationReport extends Report {
+    protected Kind kind;
+    protected String message;
+    protected String sourceString;
+    protected int position;
+    protected int startPosition;
+    protected int endPosition;
+    protected Element sourceElement;
+    protected AnnotationMirror annotationMirror;
+    protected AnnotationValue annotationValue;
+
+    /**
+     * Constructs a new ContractDiagnostic.
+     *
+     * @param kind the kind of this diagnostic
+     * @param message the message of this diagnostic
+     * @param sourceString the code of the contract
+     * @param position the position of the error
+     * @param startPosition the start position of the error
+     * @param endPosition the end position of the error
+     * @param sourceElement the source of this diagnostic
+     * @param annotationMirror the source annotation of this diagnostic
+     * @param annotationValue the source annotation value of this diagnostic
+     */
+    @Requires({
+      "kind != null",
+      "message != null",
+      "position >= startPosition",
+      "position <= endPosition",
+      "startPosition >= 0",
+      "startPosition <= endPosition"
+    })
+    @Ensures({
+      "kind == getKind()"
+    })
+    public AnnotationReport(Kind kind, String message, String sourceString,
+        int position, int startPosition, int endPosition,
+        Element sourceElement,
+        AnnotationMirror annotationMirror, AnnotationValue annotationValue) {
+      this.kind = kind;
+      this.message = message;
+      this.sourceString = sourceString;
+      this.position = position;
+      this.startPosition = startPosition;
+      this.endPosition = endPosition;
+      this.sourceElement = sourceElement;
+      this.annotationMirror = annotationMirror;
+      this.annotationValue = annotationValue;
+    }
+
+    /**
+     * Constructs a new ContractDiagnostic.
+     *
+     * @param kind the kind of this diagnostic
+     * @param message the message of this diagnostic
+     * @param sourceString the code of the contract
+     * @param position the position of the error
+     * @param startPosition the start position of the error
+     * @param endPosition the end position of the error
+     * @param info the source of this diagnostic
+     */
+    @Requires({
+      "kind != null",
+      "message != null",
+      "position >= startPosition",
+      "position <= endPosition",
+      "startPosition >= 0",
+      "startPosition <= endPosition"
+    })
+    @Ensures({
+      "kind == getKind()"
+    })
+    public AnnotationReport(Kind kind, String message, String sourceString,
+        int position, int startPosition, int endPosition, Object info) {
+      this(kind, message, sourceString, position, startPosition, endPosition,
+           null, null, null);
+      if (info instanceof AnnotationSourceInfo) {
+        AnnotationSourceInfo sourceInfo = (AnnotationSourceInfo) info;
+        sourceElement = sourceInfo.getElement();
+        annotationMirror = sourceInfo.getAnnotationMirror();
+        annotationValue = sourceInfo.getAnnotationValue();
+      }
+    }
+
+    @Override
+    public Kind getKind() {
+      return kind;
+    }
+
+    @Override
+    public String getMessage(Locale locale) {
+      if (sourceString == null) {
+        return message;
+      }
+      StringBuilder buffer = new StringBuilder("clause: ");
+      buffer.append(sourceString);
+      buffer.append("\n        ");
+      underlineError(buffer, sourceString, position,
+                     startPosition, endPosition);
+      return message + "\n" + buffer.toString();
+    }
+
+    @Override
+    public Element getElement() {
+      return sourceElement;
+    }
+
+    @Override
+    public AnnotationMirror getAnnotationMirror() {
+      return annotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getAnnotationValue() {
+      return annotationValue;
+    }
+  }
+
+  /**
+   * A diagnostic issued by an underlying compiler invocation.
+   *
+   * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+   */
+  @Invariant("diagnostic != null")
+  public class CompilerReport extends Report {
+    protected Diagnostic<? extends JavaFileObject> diagnostic;
+
+    /**
+     * Constructs a new CompilerReport based on
+     * {@code diagnostic}.
+     */
+    @Requires("diagnostic != null")
+    public CompilerReport(
+        Diagnostic<? extends JavaFileObject> diagnostic) {
+      this.diagnostic = diagnostic;
+    }
+
+    /**
+     * Formats a pretty-printed snippet around where the error
+     * occurred. The returned snippet has the faulty sequence
+     * underlined, if possible.
+     */
+    @Requires({
+      "sourceContent != null",
+      "sourceInfo != null"
+    })
+    protected String formatErrorSnippet(CharSequence sourceContent,
+                                        AnnotationSourceInfo sourceInfo) {
+      List<String> code = sourceInfo.getCode();
+      int column = (int) diagnostic.getColumnNumber();
+
+      /*
+       * Determine length of extra context to ensure we match the code
+       * expressions entirely.
+       */
+      int maxCodeLength = 0;
+      for (String expr : code) {
+        int length = expr.length();
+        if (length > maxCodeLength) {
+          maxCodeLength = length;
+        }
+      }
+
+      /* Fetch context. */
+      int errorPos = (int) diagnostic.getPosition();
+      int lineStart = errorPos - column + 1;
+      int errorStart = (int) diagnostic.getStartPosition();
+      int errorEnd = (int) diagnostic.getEndPosition();
+      String partialLine = sourceContent
+          .subSequence(lineStart, errorEnd)
+          .toString();
+
+      /* Match failed expression. */
+      String snippet = null;
+      int snippetErrorPos = -1;
+      int snippetErrorStart = -1;
+      int snippetErrorEnd = -1;
+      for (String expr : code) {
+        /* Find debug marker. */
+        String commentMarker =
+            JavaUtils.BEGIN_LOCATION_COMMENT
+            + JavaUtils.quoteComment(expr)
+            + JavaUtils.END_LOCATION_COMMENT;
+        int pos = partialLine.lastIndexOf(commentMarker);
+        if (pos != -1) {
+          snippet = expr;
+          pos += commentMarker.length();
+
+          /* Compute generated code offsets. */
+          int base = lineStart + pos;
+          snippetErrorPos = errorPos - base;
+          snippetErrorStart = errorStart - base;
+          snippetErrorEnd = errorEnd - base;
+
+          snippetErrorPos -= JavaUtils.generatedCodeLength(
+              partialLine.substring(pos, pos + snippetErrorPos));
+          snippetErrorStart -= JavaUtils.generatedCodeLength(
+              partialLine.substring(pos, pos + snippetErrorStart));
+          snippetErrorEnd -= JavaUtils.generatedCodeLength(
+              partialLine.substring(pos, pos + snippetErrorEnd));
+        }
+      }
+
+      if (snippet != null) {
+        StringBuilder buffer = new StringBuilder("clause: ");
+        buffer.append(snippet);
+        if (snippetErrorPos != -1) {
+          buffer.append("\n        ");
+          int end = snippet.length();
+          if (snippetErrorPos > end) {
+            snippetErrorPos = end;
+          }
+          if (snippetErrorStart > end) {
+            snippetErrorStart = end;
+          }
+          if (snippetErrorEnd > end) {
+            snippetErrorEnd = end;
+          }
+          underlineError(buffer, snippet, snippetErrorPos,
+                         snippetErrorStart, snippetErrorEnd);
+          snippet = buffer.toString();
+        }
+      }
+      return snippet;
+    }
+
+    /**
+     * Returns the {@link AnnotationSourceInfo} object associated with
+     * the underlying {@link Diagnostic}, if any.
+     */
+    protected AnnotationSourceInfo getSourceInfo() {
+      JavaFileObject source = diagnostic.getSource();
+      if (!(source instanceof SyntheticJavaFile)) {
+        return null;
+      }
+      SyntheticJavaFile synthSource = (SyntheticJavaFile) source;
+      Object info = synthSource.getSourceInfo(diagnostic.getLineNumber());
+      if (!(info instanceof AnnotationSourceInfo)) {
+        return null;
+      }
+      return (AnnotationSourceInfo) info;
+    }
+
+    @Override
+    public Kind getKind() {
+      return diagnostic.getKind();
+    }
+
+    @Override
+    public String getMessage(Locale locale) {
+      AnnotationSourceInfo sourceInfo = getSourceInfo();
+      String msg = "error in contract: ";
+
+      /*
+       * This translates confusing "'<token>' expected" messages from
+       * javac to plain "syntax error" messages.
+       *
+       * TODO(lenh): Think of a more generic way to handle
+       * compiler-specific error message rewriting.
+       */
+      String errorCode = diagnostic.getCode();
+      if (errorCode != null
+          && errorCode.startsWith("compiler.err.expected")) {
+        msg += "syntax error";
+      } else {
+        msg += diagnostic.getMessage(locale);
+      }
+
+      JavaFileObject source = diagnostic.getSource();
+      if (source != null && sourceInfo != null) {
+        try {
+          CharSequence chars = source.getCharContent(true);
+          return msg + "\n" + formatErrorSnippet(chars, sourceInfo);
+        } catch (IOException e) {
+          /* No source code available. */
+        }
+      }
+
+      return msg;
+    }
+
+    @Override
+    public Element getElement() {
+      AnnotationSourceInfo sourceInfo = getSourceInfo();
+      return getSourceInfo() == null ? null : sourceInfo.getElement();
+    }
+
+    @Override
+    public AnnotationMirror getAnnotationMirror() {
+      AnnotationSourceInfo sourceInfo = getSourceInfo();
+      return getSourceInfo() == null
+          ? null : sourceInfo.getAnnotationMirror();
+    }
+
+    @Override
+    public AnnotationValue getAnnotationValue() {
+      AnnotationSourceInfo sourceInfo = getSourceInfo();
+      return getSourceInfo() == null
+          ? null : sourceInfo.getAnnotationValue();
+    }
+  }
+
+  protected List<Report> reports;
+  protected int errorCount;
+
+  public DiagnosticManager() {
+    reports = new ArrayList<Report>();
+    errorCount = 0;
+  }
+
+  public boolean hasErrors() {
+    return errorCount != 0;
+  }
+
+  @Ensures("result >= 0")
+  public int getErrorCount() {
+    return errorCount;
+  }
+
+  @Ensures("result >= 0")
+  public int getCount() {
+    return reports.size();
+  }
+
+  @Override
+  public Iterator<Report> iterator() {
+    return reports.iterator();
+  }
+
+  /**
+   * Adds {@code r} to the list of reports of this manager.
+   */
+  @Requires("r != null")
+  public void report(Report r) {
+    if (r.getKind() == Kind.ERROR) {
+      ++errorCount;
+    }
+    reports.add(r);
+  }
+
+  /**
+   * Reports a compiler diagnostic. This diagnostic manager only
+   * reports errors from the underlying compiler tool invocation,
+   * which calls this method; anything other than an error is
+   * ignored. This prevents the annotation processor from picking up
+   * irrelevant warnings pertaining to generated code.
+   */
+  @Override
+  public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+    if (diagnostic.getKind() != Kind.ERROR)
+      return;
+    report(new CompilerReport(diagnostic));
+  }
+
+  /**
+   * Reports an error.
+   */
+  public void error(String message, String sourceString,
+                    int position, int startPosition, int endPosition,
+                    Object info) {
+    report(new AnnotationReport(Kind.ERROR, message, sourceString,
+                                position, startPosition, endPosition, info));
+  }
+
+  public void error(String message, String sourceString,
+                    int position, int startPosition, int endPosition,
+                    Element sourceElement, AnnotationMirror annotationMirror,
+                    AnnotationValue annotationValue) {
+    report(new AnnotationReport(Kind.ERROR, message, sourceString,
+                                position, startPosition, endPosition,
+                                sourceElement, annotationMirror,
+                                annotationValue));
+  }
+
+  /**
+   * Reports a warning.
+   */
+  public void warning(String message, String sourceString,
+                      int position, int startPosition, int endPosition,
+                      Object info) {
+    report(new AnnotationReport(Kind.WARNING, message, sourceString,
+                                position, startPosition, endPosition, info));
+  }
+
+  public void warning(String message, String sourceString,
+                      int position, int startPosition, int endPosition,
+                      Element sourceElement, AnnotationMirror annotationMirror,
+                      AnnotationValue annotationValue) {
+    report(new AnnotationReport(Kind.WARNING, message, sourceString,
+                                position, startPosition, endPosition,
+                                sourceElement, annotationMirror,
+                                annotationValue));
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/FactoryUtils.java b/src/com/google/java/contract/core/apt/FactoryUtils.java
new file mode 100644
index 0000000..aa1c4d3
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/FactoryUtils.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModifier;
+import com.google.java.contract.core.model.QualifiedElementModel;
+import com.google.java.contract.core.model.TypeName;
+
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+
+/**
+ * Utility methods for dealing with {@link javax.lang.model} and their
+ * {@link com.google.java.contract.core.apt} counterparts.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "processingEnv != null",
+  "elementUtils != null",
+  "typeUtils != null"
+})
+class FactoryUtils {
+  ProcessingEnvironment processingEnv;
+  Elements elementUtils;
+  Types typeUtils;
+
+  @Requires("processingEnv != null")
+  @Ensures({
+    "this.processingEnv == processingEnv",
+    "elementUtils == processingEnv.getElementUtils()",
+    "typeUtils == processingEnv.getTypeUtils()"
+  })
+  FactoryUtils(ProcessingEnvironment processingEnv) {
+    this.processingEnv = processingEnv;
+    elementUtils = processingEnv.getElementUtils();
+    typeUtils = processingEnv.getTypeUtils();
+  }
+
+  void copyModifiers(Element e, QualifiedElementModel model) {
+    for (ElementModifier modifier :
+         ElementModifier.forModifiers(e.getModifiers())) {
+      model.addModifier(modifier);
+    }
+  }
+
+  /**
+   * Creates a {@link ClassName} from a {@link TypeMirror}. The
+   * created ClassName bears generic parameters, if any.
+   */
+  @Requires({
+    "type != null",
+    "type.getKind() == javax.lang.model.type.TypeKind.DECLARED"
+  })
+  @Ensures("result == null || result.getDeclaredName().equals(type.toString())")
+  ClassName getClassNameForType(TypeMirror type) {
+    DeclaredType tmp = (DeclaredType) type;
+    TypeElement element = (TypeElement) tmp.asElement();
+    String binaryName = elementUtils.getBinaryName(element)
+        .toString().replace('.', '/');
+    return new ClassName(binaryName, type.toString());
+  }
+
+  /**
+   * Creates a {@link TypeName} from a {@link TypeMirror}.
+   */
+  @Requires("type != null")
+  @Ensures("result == null || result.getDeclaredName().equals(type.toString())")
+  TypeName getTypeNameForType(TypeMirror type) {
+    switch (type.getKind()) {
+      case NONE:
+        return null;
+      default:
+        return new TypeName(type.toString());
+    }
+  }
+
+  /**
+   * Returns a Java-printable generic type name from the specified
+   * TypeParameterElement.
+   */
+  @Requires("element != null")
+  @Ensures("result != null")
+  TypeName getGenericTypeName(TypeParameterElement element) {
+    String name = element.getSimpleName().toString();
+    List<? extends TypeMirror> bounds = element.getBounds();
+    if (bounds.isEmpty()
+        || (bounds.size() == 1
+            && bounds.get(0).toString().equals("java.lang.Object"))) {
+      return new TypeName(name);
+    }
+
+    StringBuilder buffer = new StringBuilder();
+    buffer.append(name);
+    buffer.append(" extends ");
+
+    Iterator<? extends TypeMirror> iter = bounds.iterator();
+    for (;;) {
+      buffer.append(iter.next().toString());
+      if (!iter.hasNext()) {
+        break;
+      }
+      buffer.append(" & ");
+    }
+
+    return new TypeName(buffer.toString());
+  }
+
+  /**
+   * Gets the contract kind of an annotation given its qualified name.
+   * Returns null if the annotation is not a contract annotation.
+   *
+   * @param annotationName the fully qualified name of the annotation
+   * @return the contract type, null if not contracts
+   */
+  ElementKind getAnnotationKindForName(AnnotationMirror annotation) {
+    String annotationName = annotation.getAnnotationType().toString();
+    ElementKind kind;
+    if (annotationName.equals("com.google.java.contract.Invariant")) {
+      kind = ElementKind.INVARIANT;
+    } else if (annotationName.equals("com.google.java.contract.Requires")) {
+      kind = ElementKind.REQUIRES;
+    } else if (annotationName.equals("com.google.java.contract.Ensures")) {
+      kind = ElementKind.ENSURES;
+    } else if (annotationName.equals("com.google.java.contract.ThrowEnsures")) {
+      kind = ElementKind.THROW_ENSURES;
+    } else {
+      kind = null;
+    }
+
+    return kind;
+  }
+
+  boolean isContractAnnotation(AnnotationMirror annotation) {
+    return getAnnotationKindForName(annotation) != null;
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/JavacUtils.java b/src/com/google/java/contract/core/apt/JavacUtils.java
new file mode 100644
index 0000000..6157c8b
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/JavacUtils.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.sun.source.tree.AnnotationTree;
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.ExpressionTree;
+import com.sun.source.tree.ImportTree;
+import com.sun.source.tree.LineMap;
+import com.sun.source.tree.NewArrayTree;
+import com.sun.source.tree.Tree.Kind;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.Trees;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+
+/**
+ * A com.sun.source-based utility class that extracts source
+ * information.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+class JavacUtils {
+  /**
+   * Returns the line numbers associated with {@code annotation}.
+   */
+  @Requires({
+    "processingEnv != null",
+    "element != null",
+    "annotation != null"
+  })
+  @Ensures("result != null")
+  public static List<Long> getLineNumbers(ProcessingEnvironment processingEnv,
+      Element element, AnnotationMirror annotation) {
+    Trees treeUtils = Trees.instance(processingEnv);
+    if (treeUtils == null) {
+      return Collections.emptyList();
+    }
+
+    TreePath path = treeUtils.getPath(element, annotation);
+    if (path == null) {
+      return Collections.emptyList();
+    }
+
+    CompilationUnitTree unitTree = path.getCompilationUnit();
+    LineMap lineMap = unitTree.getLineMap();
+    SourcePositions positions = treeUtils.getSourcePositions();
+
+    AnnotationTree annotationTree = (AnnotationTree) path.getLeaf();
+    AssignmentTree assignTree =
+        (AssignmentTree) annotationTree.getArguments().get(0);
+    ExpressionTree exprTree = assignTree.getExpression();
+
+    ArrayList<Long> lines = new ArrayList<Long>();
+    if (exprTree.getKind() == Kind.STRING_LITERAL) {
+      long pos = positions.getStartPosition(unitTree, exprTree);
+      lines.add(lineMap.getLineNumber(pos));
+    } else {
+      NewArrayTree valuesTree = (NewArrayTree) exprTree;
+      for (ExpressionTree valueTree : valuesTree.getInitializers()) {
+        long pos = positions.getStartPosition(unitTree, valueTree);
+        lines.add(lineMap.getLineNumber(pos));
+      }
+    }
+
+    return lines;
+  }
+
+  /**
+   * Returns the import statements in effect in the containing
+   * compilation unit of {@code element}.
+   */
+  @Requires({
+    "processingEnv != null",
+    "element != null"
+  })
+  @Ensures("result != null")
+  public static Set<String> getImportNames(ProcessingEnvironment processingEnv,
+      Element element) {
+    Trees treeUtils = Trees.instance(processingEnv);
+    if (treeUtils == null) {
+      return Collections.emptySet();
+    }
+
+    TreePath path = treeUtils.getPath(element);
+    if (path == null) {
+      return Collections.emptySet();
+    }
+
+    CompilationUnitTree unitTree = path.getCompilationUnit();
+
+    HashSet<String> importNames = new HashSet<String>();
+    for (ImportTree importTree : unitTree.getImports()) {
+      StringBuilder buffer = new StringBuilder();
+      if (importTree.isStatic()) {
+        buffer.append("static ");
+      }
+      /* TODO(lenh): Roll our own toString()? */
+      buffer.append(importTree.getQualifiedIdentifier().toString());
+      importNames.add(buffer.toString());
+    }
+
+    return importNames;
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/MethodContractCreator.java b/src/com/google/java/contract/core/apt/MethodContractCreator.java
new file mode 100644
index 0000000..ff7d249
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/MethodContractCreator.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import static com.google.java.contract.core.apt.ContractCreation.createContractMethods;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ContractKind;
+import com.google.java.contract.core.model.ContractMethodModel;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModifier;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.TypeName;
+import com.google.java.contract.core.model.VariableModel;
+import com.google.java.contract.core.util.ElementScanner;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Element visitor responsible for decorating a {@link TypeModel}
+ * object with method-wide contract code elements.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "diagnosticManager != null",
+  "transformer != null"
+})
+public class MethodContractCreator extends ElementScanner {
+  /**
+   * Creation trait for preconditions.
+   */
+  protected class PreMethodCreationTrait
+      extends ContractExpressionCreationTrait {
+    @Requires("transformer != null")
+    public PreMethodCreationTrait(
+        ContractExpressionTransformer transformer) {
+      super(transformer);
+    }
+
+    @Override
+    public boolean transform(List<String> code, List<Long> lineNumbers,
+                             Object sourceInfo) {
+      transformer.setAcceptOld(false);
+      return super.transform(code, lineNumbers, sourceInfo);
+    }
+
+    @Override
+    public String getExceptionName() {
+      return "com.google.java.contract.PreconditionError";
+    }
+  }
+
+  /**
+   * Creation trait for common transformations shared by
+   * postconditions and exceptional postconditions.
+   */
+  protected class CommonPostMethodCreationTrait
+      extends ContractExpressionCreationTrait {
+    @Requires("transformer != null")
+    public CommonPostMethodCreationTrait(
+        ContractExpressionTransformer transformer) {
+      super(transformer);
+    }
+
+    @Override
+    public boolean transform(List<String> code, List<Long> lineNumbers,
+                              Object sourceInfo) {
+      int id = transformer.getNextOldId();
+      transformer.setAcceptOld(true);
+      boolean success = super.transform(code, lineNumbers, sourceInfo);
+
+      if (success) {
+        ContractKind oldKind =
+            ContractCreation.getContractKind(annotation).getOldKind();
+        Iterator<String> iterCode =
+            transformer.getOldParametersCode().iterator();
+        Iterator<Long> iterLineNumber =
+            transformer.getOldParametersLineNumbers().iterator();
+        int pos = 0;
+        while (iterCode.hasNext()) {
+          createOldMethods(oldKind, pos++, id++, iterCode.next(), annotation,
+                           iterLineNumber.next());
+        }
+      }
+      return success;
+    }
+
+    @Override
+    public List<? extends VariableModel> getExtraParameters() {
+      return transformer.getOldParameters();
+    }
+
+    @Override
+    public String getExceptionName() {
+      return "com.google.java.contract.PostconditionError";
+    }
+  }
+
+  /**
+   * Creation trait for postconditions.
+   */
+  protected class PostMethodCreationTrait
+      extends CommonPostMethodCreationTrait {
+    @Requires("transformer != null")
+    public PostMethodCreationTrait(
+        ContractExpressionTransformer transformer) {
+      super(transformer);
+    }
+
+    @Override
+    public List<? extends VariableModel> getInitialParameters() {
+      if (method.isConstructor()
+          || method.getReturnType().getDeclaredName().equals("void")) {
+        return Collections.emptyList();
+      } else {
+        return Collections.singletonList(
+            getResultVariable(method.getReturnType()));
+      }
+    }
+
+    @Override
+    public List<? extends VariableModel> getInitialMockParameters() {
+      if (method.isConstructor()
+          || method.getReturnType().getDeclaredName().equals("void")) {
+        return Collections.emptyList();
+      } else {
+        return Collections.singletonList(
+            getResultVariable(annotation.getReturnType()));
+      }
+    }
+  }
+
+  /**
+   * Creation trait for exceptional postconditions.
+   */
+  protected class PostSignalMethodCreationTrait
+      extends CommonPostMethodCreationTrait {
+    protected List<String> messages;
+    protected List<String> sourceCode;
+
+    @Requires("transformer != null")
+    public PostSignalMethodCreationTrait(
+        ContractExpressionTransformer transformer) {
+      super(transformer);
+    }
+
+    @Override
+    public boolean visit(ContractAnnotationModel annotation) {
+      this.annotation = annotation;
+
+      List<String> assocs = annotation.getValues();
+      int n = assocs.size() / 2;
+
+      ArrayList<String> code = new ArrayList<String>(n);
+      ArrayList<String> msg = new ArrayList<String>(n);
+      ArrayList<String> src = new ArrayList<String>(n);
+      ArrayList<Long> lines = new ArrayList<Long>(n);
+
+      Iterator<String> it = assocs.iterator();
+      Iterator<Long> itLineNumber = annotation.getLineNumbers().iterator();
+      try {
+        while (it.hasNext()) {
+          String exceptionType = it.next();
+          String postcondition = it.next();
+          code.add("!(signal instanceof " + exceptionType + ") || "
+                   + postcondition);
+          msg.add(exceptionType + " => " + postcondition);
+          src.add(postcondition);
+
+          /*
+           * Throw away the line number information of the exception
+           * type.
+           */
+          itLineNumber.next();
+          lines.add(itLineNumber.next());
+        }
+      } catch (NoSuchElementException e) {
+        diagnosticManager.warning(
+            "extra exception type in "
+            + "'com.google.java.contract.ThrowEnsures'; "
+            + "ignored",
+            assocs.get(assocs.size() - 1), 0, 0, 0,
+            annotation.getSourceInfo());
+      }
+
+      if (!transform(code, lines, annotation.getSourceInfo())) {
+        return false;
+      }
+
+      messages = msg;
+      sourceCode = src;
+      return true;
+    }
+
+    @Override
+    public List<? extends VariableModel> getInitialParameters() {
+      return Collections.singletonList(getSignalVariable());
+    }
+
+    @Override
+    public List<String> getMessages() {
+      return messages;
+    }
+
+    @Override
+    public List<String> getSourceExpressions() {
+      return sourceCode;
+    }
+  }
+
+  protected DiagnosticManager diagnosticManager;
+
+  protected MethodModel method;
+  protected ContractMethodModel preMethod;
+  protected ContractMethodModel postMethod;
+  protected ContractMethodModel postSignalMethod;
+
+  protected ContractExpressionTransformer transformer;
+
+  /**
+   * Constructs a new MethodContractCreator.
+   */
+  @Requires("diagnosticManager != null")
+  public MethodContractCreator(DiagnosticManager diagnosticManager) {
+    this.diagnosticManager = diagnosticManager;
+    method = null;
+    preMethod = null;
+    postMethod = null;
+    postSignalMethod = null;
+    transformer = new ContractExpressionTransformer(diagnosticManager, true);
+  }
+
+  @Override
+  public void visitMethod(MethodModel method) {
+    if (this.method != null) {
+      throw new IllegalStateException();
+    }
+    this.method = method;
+    super.visitMethod(method);
+  }
+
+  @Override
+  public void visitContractAnnotation(ContractAnnotationModel annotation) {
+    List<String> code = annotation.getValues();
+
+    if (annotation.getKind().equals(ElementKind.REQUIRES)) {
+      PreMethodCreationTrait trait = new PreMethodCreationTrait(transformer);
+      preMethod = createContractMethods(trait, preMethod, annotation);
+    } else if (annotation.getKind().equals(ElementKind.ENSURES)) {
+      PostMethodCreationTrait trait = new PostMethodCreationTrait(transformer);
+      postMethod = createContractMethods(trait, postMethod, annotation);
+    } else if (annotation.getKind().equals(ElementKind.THROW_ENSURES)) {
+      PostSignalMethodCreationTrait trait =
+          new PostSignalMethodCreationTrait(transformer);
+      postSignalMethod = createContractMethods(trait, postSignalMethod,
+                                               annotation);
+    } else {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  @Requires("type != null")
+  @Ensures("result != null")
+  private static VariableModel getResultVariable(TypeName type) {
+    VariableModel var =
+        new VariableModel(ElementKind.PARAMETER, JavaUtils.RESULT_VARIABLE,
+                          type);
+    var.addModifier(ElementModifier.FINAL);
+    return var;
+  }
+
+  @Ensures("result != null")
+  private static VariableModel getSignalVariable() {
+    VariableModel var =
+        new VariableModel(ElementKind.PARAMETER, JavaUtils.SIGNAL_VARIABLE,
+                          new ClassName("java/lang/Exception"));
+    var.addModifier(ElementModifier.FINAL);
+    return var;
+  }
+
+  /**
+   * Creates contract and helper methods according to the parameters,
+   * and adds it to the parent type.
+   *
+   * @param kind the kind of contract method to create
+   * @param pos the relative position of {@code expr} in its
+   * annotation
+   * @param id the contract method ID
+   * @param expr the expression computing the old value
+   * @param annotation the annotation value from which this contract
+   * is created
+   */
+  @Requires({
+    "kind != null",
+    "pos >= 0",
+    "id >= 0",
+    "pos <= id",
+    "expr != null",
+    "annotation != null",
+    "kind.isOld()",
+    "lineNumber == null || lineNumber >= 1"
+  })
+  private void createOldMethods(ContractKind kind,
+      int pos, int id, String expr, ContractAnnotationModel annotation,
+      Long lineNumber) {
+    MethodModel helper =
+        ContractCreation.createBlankContractHelper(kind, annotation,
+                                                   "$" + Integer.toString(pos));
+    helper.setReturnType(new ClassName("java/lang/Object"));
+
+    if (helper.getKind() == ElementKind.CONTRACT_METHOD) {
+      ContractMethodModel helperContract = (ContractMethodModel) helper;
+      if (lineNumber != null) {
+        helperContract.setLineNumbers(Collections.singletonList(lineNumber));
+      }
+      String code = expr;
+      if (!annotation.isVirtual()) {
+        code = ContractCreation
+            .rebaseLocalCalls(expr, JavaUtils.THAT_VARIABLE, null);
+      }
+      helperContract.addStatement("return " + code + ";");
+    }
+
+    ContractMethodModel contract =
+        ContractCreation.createBlankContractMethod(kind, annotation, "$" + id);
+    contract.setReturnType(new ClassName("java/lang/Object"));
+    contract.setId(id);
+
+    contract.addStatement("return "
+        + ContractCreation.getHelperCallCode(helper, annotation) + ";");
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/SimpleContractCreationTrait.java b/src/com/google/java/contract/core/apt/SimpleContractCreationTrait.java
new file mode 100644
index 0000000..6425b68
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/SimpleContractCreationTrait.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.VariableModel;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A simple contract creation trait that returns the annotation values
+ * unmodified.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+class SimpleContractCreationTrait implements ContractCreationTrait {
+  protected ContractAnnotationModel annotation;
+
+  @Override
+  public boolean visit(ContractAnnotationModel annotation) {
+    this.annotation = annotation;
+    return true;
+  }
+
+  @Override
+  public List<String> getExpressions() {
+    return annotation.getValues();
+  }
+
+  @Override
+  public List<String> getMessages() {
+    return annotation.getValues();
+  }
+
+  @Override
+  public List<String> getSourceExpressions() {
+    return annotation.getValues();
+  }
+
+  @Override
+  public List<? extends VariableModel> getInitialParameters() {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public List<? extends VariableModel> getExtraParameters() {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public List<? extends VariableModel> getInitialMockParameters() {
+    return getInitialParameters();
+  }
+
+  @Override
+  public List<? extends VariableModel> getExtraMockParameters() {
+    return getExtraParameters();
+  }
+
+  @Override
+  public String getExceptionName() {
+    return "java.lang.AssertionError";
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/SourceDependencyParser.java b/src/com/google/java/contract/core/apt/SourceDependencyParser.java
new file mode 100644
index 0000000..be868b8
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/SourceDependencyParser.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.util.BalancedTokenizer;
+import com.google.java.contract.core.util.JavaTokenizer;
+import com.google.java.contract.core.util.JavaUtils;
+import com.google.java.contract.core.util.JavaUtils.ParseException;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A flexible parser that extracts import statements and line number
+ * information from a Java source file.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at AllowUnusedImport({ Iterables.class, Predicates.class })
+ at Invariant({
+  "!canQueryResults() || getImportNames() != null",
+  "!canQueryResults() || !getImportNames().contains(null)",
+  "!canQueryResults() || getContractLineNumbers() != null",
+  "!canQueryResults() || !getContractLineNumbers().entrySet().contains(null)",
+  "!canQueryResults() || " +
+      "Iterables.all(getContractLineNumbers().values(), " +
+      "    Predicates.<Long>all(Predicates.between(1L, null)))",
+  "source != null"
+})
+public class SourceDependencyParser {
+  /**
+   * The source file being parsed.
+   */
+  protected Reader source;
+
+  /**
+   * A set of import targets that are in effect in the source file.
+   */
+  protected Set<String> importNames;
+
+  /**
+   * The successive positions of contracts in the source file, in each
+   * top-level class. Each clause has an entry in the list. Each entry
+   * for a top-level class includes contracts in nested classes.
+   */
+  protected Map<ClassName, List<Long>> contractLineNumbers;
+
+  /**
+   * Whether {@code source} has been parsed yet.
+   */
+  protected boolean parsed;
+
+  private static final List<String> TYPE_KEYWORDS =
+      Arrays.asList("class", "enum", "interface");
+  private static final List<String> CONTRACT_TYPES =
+      Arrays.asList("Requires", "Ensures", "ThrowEnsures", "Invariant");
+
+  /**
+   * Constructs a new SourceDependencyParser.
+   *
+   * @param source the source file
+   */
+  public SourceDependencyParser(Reader source) {
+    this.source = source;
+    importNames = new HashSet<String>();
+    contractLineNumbers = new HashMap<ClassName, List<Long>>();
+    parsed = false;
+  }
+
+  /**
+   * Parses the source file.
+   *
+   * @throws ParseException if a parsing error occurs
+   */
+  @Ensures("canQueryResults()")
+  public void parse() throws ParseException {
+    if (parsed) {
+      return;
+    }
+
+    try {
+      BalancedTokenizer tokenizer = new BalancedTokenizer(source);
+      String packageName = null;
+      ClassName className = null;
+      ArrayList<Long> orphanLineNumbers = new ArrayList<Long>();
+      while (tokenizer.hasNext()) {
+        JavaTokenizer.Token token = tokenizer.next();
+        switch (token.kind) {
+          case WORD:
+            if (tokenizer.getCurrentLevel() == 0) {
+              if (token.text.equals("package")) {
+                packageName = JavaUtils.parseQualifiedName(tokenizer);
+              } else if (token.text.equals("import")) {
+                String name = JavaUtils.parseQualifiedName(tokenizer, true);
+                if (name.equals("static")) {
+                  name += " " + JavaUtils.parseQualifiedName(tokenizer, true);
+                }
+                importNames.add(name);
+              } else if (TYPE_KEYWORDS.contains(token.text)) {
+                String name = JavaUtils.parseQualifiedName(tokenizer);
+                if (packageName != null) {
+                  name = packageName + "." + name;
+                }
+                className = new ClassName(name.replace('.', '/'));
+                contractLineNumbers
+                    .put(className, new ArrayList<Long>(orphanLineNumbers));
+                orphanLineNumbers.clear();
+                JavaUtils.skipPast(tokenizer, "{");
+              }
+            }
+            break;
+
+          case SYMBOL:
+            if (tokenizer.getCurrentLevel() == 0 && token.text.equals("}")) {
+              className = null;
+            } else {
+              if (token.text.equals("@")) {
+                String annotationType = JavaUtils.parseQualifiedName(tokenizer);
+                if (annotationType.startsWith("com.google.java.contract.")
+                    || (CONTRACT_TYPES.contains(annotationType)
+                        && ((packageName != null
+                             && packageName.equals("com.google.java.contract"))
+                            || importNames.contains("com.google.java.contract."
+                                                    + annotationType)
+                            || importNames.contains("com.google.java.contract.*")))) {
+                  List<Long> lineNumbers;
+                  if (className != null) {
+                    lineNumbers = contractLineNumbers.get(className);
+                  } else {
+                    lineNumbers = orphanLineNumbers;
+                  }
+                  parseContractClauses(tokenizer, lineNumbers);
+                }
+              }
+            }
+            break;
+
+          default:
+            break;
+        }
+      }
+      parsed = true;
+    } catch (NoSuchElementException e) {
+      throw new ParseException(e);
+    }
+  }
+
+  @Requires({
+    "tokenizer != null",
+    "lineNumbers != null"
+  })
+  private void parseContractClauses(BalancedTokenizer tokenizer,
+                                    List<Long> lineNumbers) {
+    boolean expectClause = true;
+    while (tokenizer.hasNext()) {
+      long lineNumber = tokenizer.getCurrentLineNumber();
+      JavaTokenizer.Token token = tokenizer.next();
+      if (token.text.equals(")")) {
+        return;
+      } else if (expectClause && token.kind == JavaTokenizer.TokenKind.QUOTE) {
+        lineNumbers.add(lineNumber);
+        expectClause = false;
+      } else if (token.text.equals(",")) {
+        expectClause = true;
+      }
+    }
+  }
+
+  public boolean canQueryResults() {
+    return parsed;
+  }
+
+  @Requires("canQueryResults()")
+  public Set<String> getImportNames() {
+    return Collections.unmodifiableSet(importNames);
+  }
+
+  @Requires("canQueryResults()")
+  public Map<ClassName, List<Long>> getContractLineNumbers() {
+    return Collections.unmodifiableMap(contractLineNumbers);
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/SourcePreprocessor.java b/src/com/google/java/contract/core/apt/SourcePreprocessor.java
new file mode 100644
index 0000000..80e7021
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/SourcePreprocessor.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.util.JavaUtils;
+import com.google.java.contract.core.util.JavaUtils.ParseException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.ObjectOutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Main class of Contracts for Java source dependency preprocessor.
+ *
+ * <p>The program takes a list of file names as input and produces
+ * matching source dependency files as output. If the system property
+ * {@code com.google.java.contract.depsoutput} is defined, then dependency files
+ * are output in that directory, following the natural hierarchy of
+ * the Java classes.
+ *
+ * <p>If a source file name does not end with the {@code .java}
+ * extension, that extension is appended to the file name.
+ *
+ * <p>Source dependency files contain information about import
+ * statements in effect in the corresponding source file as well as
+ * line numbering information for contracts. They can be provided to
+ * the annotation processor through the {@code com.google.java.contract.depspath}
+ * option.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class SourcePreprocessor {
+  public static void main(String[] args)
+      throws IOException, ParseException {
+    String depout = System.getProperty("com.google.java.contract.depsoutput");
+    for (String arg : args) {
+      if (arg.startsWith("-")) {
+        continue;
+      }
+
+      String baseName = arg;
+      if (arg.endsWith(Kind.SOURCE.extension)) {
+        baseName = baseName
+            .substring(0, baseName.length() - Kind.SOURCE.extension.length());
+      }
+
+      File fileName = new File(baseName + Kind.SOURCE.extension);
+      String dir = fileName.getParent();
+      dir = dir == null ? "" : dir + "/";
+
+      FileInputStream in = new FileInputStream(arg);
+
+      SourceDependencyParser parser =
+          new SourceDependencyParser(new InputStreamReader(in));
+      try {
+        parser.parse();
+      } catch (ParseException e) {
+        throw new ParseException(
+            fileName + " is malformed; "
+            + "you should not compile contracts before compiling "
+            + "the actual source files; "
+            + "if this file is valid Java, you found a bug in Contracts for Java; "
+            + "please email 'davidmorgan at google.com'",
+            e);
+      }
+
+      Set<String> importNames = parser.getImportNames();
+      Map<ClassName, List<Long>> contractLineNumbers =
+          parser.getContractLineNumbers();
+
+      if (contractLineNumbers.isEmpty()) {
+        continue;
+      }
+
+      for (Map.Entry<ClassName, List<Long>> entry :
+           contractLineNumbers.entrySet()) {
+        ClassName className = entry.getKey();
+        File outputFileName;
+        if (depout == null) {
+          outputFileName = new File(dir + className.getSimpleName()
+                                    + JavaUtils.SOURCE_DEPENDENCY_EXTENSION);
+        } else {
+          outputFileName = new File(depout + "/" + className.getBinaryName()
+                                    + JavaUtils.SOURCE_DEPENDENCY_EXTENSION);
+        }
+
+        outputFileName.getParentFile().mkdirs();
+        FileOutputStream out = new FileOutputStream(outputFileName);
+        ObjectOutputStream oout = new ObjectOutputStream(out);
+
+        oout.writeObject(importNames);
+        oout.writeObject(entry.getValue());
+        oout.close();
+      }
+
+      in.close();
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/SuperCallBuilder.java b/src/com/google/java/contract/core/apt/SuperCallBuilder.java
new file mode 100644
index 0000000..57ddfca
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/SuperCallBuilder.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ElementModifier;
+import com.google.java.contract.core.model.TypeModel;
+
+import java.util.List;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.ElementScanner6;
+
+/**
+ * An element visitor that extracts constructor arguments from a
+ * callable constructor. It always picks a constructor with the
+ * broadest access level: if the original class was correct, then at
+ * least that one should be accessible.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("subtype != null")
+class SuperCallBuilder extends ElementScanner6<Void, Void> {
+  protected FactoryUtils utils;
+  protected DeclaredType typeMirror;
+  protected TypeModel subtype;
+  protected ElementModifier constructorFound;
+
+  /**
+   * Constructs a new SuperCallBuilder that builds a constructor call
+   * for {@code subtype}. The super call will be made against
+   * {@code typeMirror}, which may differ from the raw element this
+   * instance is visiting (e.g. it can be a specialized version of
+   * a generic class).
+   */
+  @Requires({
+    "subtype != null",
+    "utils != null"
+  })
+  SuperCallBuilder(DeclaredType typeMirror, TypeModel subtype,
+                   FactoryUtils utils) {
+    this.utils = utils;
+    this.typeMirror = typeMirror;
+    this.subtype = subtype;
+    constructorFound = null;
+  }
+
+  @Override
+  public Void visitType(TypeElement e, Void unused) {
+    scan(ElementFilter.constructorsIn(e.getEnclosedElements()), null);
+    return null;
+  }
+
+  @Override
+  public Void visitExecutable(ExecutableElement e, Void unused) {
+    ElementModifier v = ElementModifier.visibilityIn(
+        ElementModifier.forModifiers(e.getModifiers()));
+    if (constructorFound != null
+        && constructorFound.ordinal() <= v.ordinal()) {
+      return null;
+    }
+
+    subtype.clearSuperArguments();
+    ExecutableType execType =
+        (ExecutableType) utils.typeUtils.asMemberOf(typeMirror, e);
+    List<? extends TypeMirror> paramTypes = execType.getParameterTypes();
+    for (TypeMirror t : paramTypes) {
+      subtype.addSuperArgument(utils.getTypeNameForType(t));
+    }
+
+    constructorFound = v;
+    return null;
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/TypeBuilder.java b/src/com/google/java/contract/core/apt/TypeBuilder.java
new file mode 100644
index 0000000..65cef28
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/TypeBuilder.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModel;
+import com.google.java.contract.core.model.ElementModifier;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.VariableModel;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+/**
+ * An element visitor that builds a {@link TypeModel} object. It
+ * recursively builds child (nested) types. This visitor takes an
+ * element parameter, to which children are added.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at Invariant({
+  "diagnosticManager != null",
+  "methodMap != null"
+})
+class TypeBuilder extends AbstractTypeBuilder {
+  protected class ContractableMethod {
+    protected ExecutableElement mirror;
+    protected MethodModel element;
+
+    public ContractableMethod(ExecutableElement mirror,
+                              MethodModel element) {
+      this.mirror = mirror;
+      this.element = element;
+    }
+  }
+
+  /**
+   * An element visitor that adds inherited contract annotations to
+   * an existing TypeModel object.
+   */
+  protected class ContractExtensionBuilder extends AbstractTypeBuilder {
+    protected TypeElement mirror;
+
+    public ContractExtensionBuilder() {
+      super(TypeBuilder.this.utils, TypeBuilder.this.diagnosticManager);
+    }
+
+    @Override
+    public Void visitType(TypeElement e, ElementModel p) {
+      if (mirror != null) {
+        throw new IllegalStateException();
+      }
+
+      mirror = e;
+      scanAnnotations(e, false, utils.getClassNameForType(e.asType()), type);
+
+      scan(ElementFilter.methodsIn(e.getEnclosedElements()), type);
+
+      scanSuper(e);
+      return null;
+    }
+
+    @Override
+    public Void visitExecutable(ExecutableElement e, ElementModel p) {
+      String name = e.getSimpleName().toString();
+      ArrayList<ContractableMethod> candidates = methodMap.get(name);
+      if (candidates == null) {
+        return null;
+      }
+      for (ContractableMethod overrider : candidates) {
+        if (utils.elementUtils.overrides(overrider.mirror, e,
+                                         rootMirror)) {
+          scanAnnotations(e, false,
+                          utils.getClassNameForType(mirror.asType()),
+                          overrider.element);
+        }
+      }
+      return null;
+    }
+  }
+
+  protected ClassLoader sourceDependencyLoader;
+
+  /**
+   * The resulting top-level type.
+   */
+  protected TypeModel type;
+
+  /**
+   * The root TypeElement.
+   */
+  protected TypeElement rootMirror;
+
+  /**
+   * Import statements that apply to this type source code.
+   */
+  protected Set<String> importNames;
+
+  /**
+   * A map of resulting methods; used internally for contract
+   * inheritance propagation.
+   */
+  protected HashMap<String, ArrayList<ContractableMethod>> methodMap;
+
+  TypeBuilder(Set<String> importNames,
+              Iterator<Long> rootLineNumberIterator,
+              FactoryUtils utils,
+              ClassLoader sourceDependencyLoader,
+              DiagnosticManager diagnosticManager) {
+    super(utils, diagnosticManager);
+    this.sourceDependencyLoader = sourceDependencyLoader;
+    type = null;
+    rootMirror = null;
+    this.importNames = importNames;
+    this.rootLineNumberIterator = rootLineNumberIterator;
+    methodMap = new HashMap<String, ArrayList<ContractableMethod>>();
+  }
+
+  TypeBuilder(FactoryUtils utils,
+              ClassLoader sourceDependencyLoader,
+              DiagnosticManager diagnosticManager) {
+    this(null, null, utils, sourceDependencyLoader, diagnosticManager);
+  }
+
+  TypeModel getType() {
+    return type;
+  }
+
+  @Override
+  @Ensures("type != null")
+  public Void visitType(TypeElement e, ElementModel p) {
+    /* Inner types. */
+    if (type != null) {
+      TypeBuilder builder =
+          new TypeBuilder(importNames, rootLineNumberIterator,
+                          utils, sourceDependencyLoader, diagnosticManager);
+      e.accept(builder, p);
+      p.addEnclosedElement(builder.type);
+      return null;
+    }
+
+    /* Root type. */
+    rootMirror = e;
+
+    /* Create type. */
+    ElementKind kind = null;
+    switch (e.getKind()) {
+      case INTERFACE:
+        kind = ElementKind.INTERFACE;
+        break;
+      case ENUM:
+        kind = ElementKind.ENUM;
+        break;
+      case CLASS:
+        kind = ElementKind.CLASS;
+        break;
+      case ANNOTATION_TYPE:
+        kind = ElementKind.ANNOTATION_TYPE;
+        break;
+      default:
+        return null;
+    }
+    type = new TypeModel(kind, utils.getClassNameForType(e.asType()));
+    utils.copyModifiers(e, type);
+    if (kind == ElementKind.ENUM) {
+      type.removeModifier(ElementModifier.FINAL);
+    }
+
+    /*
+     * Fetch import and global line number information, from a
+     * source dependency file, if available, falling back to
+     * com.sun.source, if not.
+     */
+    if (importNames == null) {
+      if (sourceDependencyLoader != null) {
+        try {
+          fetchSourceDependency();
+        } catch (IOException ioe) {
+          /* Consider that no information is available. */
+        }
+      }
+      if (importNames == null) {
+        importNames = getImportNames(e);
+      }
+      for (String importName : importNames) {
+        type.addImportName(importName);
+      }
+    }
+
+    /* Set superclass and interfaces. */
+    TypeMirror superclass = e.getSuperclass();
+    if (superclass.getKind() == TypeKind.DECLARED) {
+      type.setSuperclass(utils.getClassNameForType(superclass));
+    }
+    List<? extends TypeMirror> interfaces = e.getInterfaces();
+    for (TypeMirror iface : interfaces) {
+      type.addInterface(utils.getClassNameForType(iface));
+    }
+
+    /* Construct super() call. */
+    if (kind != ElementKind.ENUM) {
+      TypeMirror superMirror = e.getSuperclass();
+      if (superMirror.getKind() == TypeKind.DECLARED) {
+        TypeElement superType =
+            (TypeElement) utils.typeUtils.asElement(superMirror);
+        SuperCallBuilder visitor =
+            new SuperCallBuilder((DeclaredType) superMirror, type, utils);
+        superType.accept(visitor, null);
+      }
+    }
+
+    /* Process generic signature. */
+    List<? extends TypeParameterElement> typeParams = e.getTypeParameters();
+    for (TypeParameterElement tp : typeParams) {
+      type.addTypeParameter(utils.getGenericTypeName(tp));
+    }
+
+    /* Process annotations. */
+    scanAnnotations(e, true, type.getName(), type);
+
+    /* Process members. */
+    scan(e.getEnclosedElements(), type);
+
+    /* Add inherited contract annotations. */
+    scanSuper(e);
+
+    return null;
+  }
+
+  @Override
+  protected void visitAnnotation(Element parent, AnnotationMirror annotation,
+                                 boolean primary, ClassName owner,
+                                 ElementModel p) {
+    if (utils.isContractAnnotation(annotation)) {
+      ContractAnnotationModel model =
+          createContractModel(parent, annotation, primary, owner);
+      if (model == null) {
+        return;
+      }
+      if (type.getKind() == ElementKind.ANNOTATION_TYPE) {
+        AnnotationSourceInfo asi = (AnnotationSourceInfo) model.getSourceInfo();
+        /* Do not add contracts to annotations. Warn the user instead. */
+        diagnosticManager.warning("Contracts can't be applied to annotations. "
+                                  + "The following annotation will not "
+                                  + "perform any contract check: " +
+                                  type.toString(),
+                                  asi.getAnnotationValue().toString(), 0, 0, 0,
+                                  asi);
+      } else {
+        p.addEnclosedElement(model);
+      }
+    }
+  }
+
+  /**
+   * Fetches source dependency information from the system class
+   * loader.
+   */
+  @Requires({
+    "sourceDependencyLoader != null",
+    "type != null"
+  })
+  @Ensures({
+    "importNames != null",
+    "rootLineNumberIterator != null"
+  })
+  @SuppressWarnings("unchecked")
+  protected void fetchSourceDependency() throws IOException {
+    String fileName = type.getName().getBinaryName()
+        + JavaUtils.SOURCE_DEPENDENCY_EXTENSION;
+    InputStream in =
+        sourceDependencyLoader.getResourceAsStream(fileName);
+    if (in == null) {
+      throw new FileNotFoundException();
+    }
+    ObjectInputStream oin = new ObjectInputStream(in);
+    try {
+      importNames = (Set<String>) oin.readObject();
+      rootLineNumberIterator = ((List<Long>) oin.readObject()).iterator();
+    } catch (ClassNotFoundException e) {
+      throw new IOException(e);
+    }
+    oin.close();
+  }
+
+  @Override
+  public Void visitVariable(VariableElement e, ElementModel p) {
+    ElementKind kind = null;
+    switch (e.getKind()) {
+      case ENUM_CONSTANT:
+        kind = ElementKind.CONSTANT;
+        break;
+      default:
+        if (p.getKind().isType()) {
+          kind = ElementKind.FIELD;
+        } else {
+          kind = ElementKind.PARAMETER;
+        }
+    }
+    VariableModel variable =
+        new VariableModel(kind, e.getSimpleName().toString(),
+                          utils.getTypeNameForType(e.asType()));
+    utils.copyModifiers(e, variable);
+
+    scanAnnotations(e, true, type.getName(), variable);
+
+    p.addEnclosedElement(variable);
+    return null;
+  }
+
+  @Override
+  public Void visitExecutable(ExecutableElement e, ElementModel p) {
+    MethodModel exec = null;
+    String name = e.getSimpleName().toString();
+
+    /*
+     * For enum types, synthesized methods values() and
+     * valueOf(String) are reflected by the API but must not be
+     * reproduced in the mock.
+     */
+    if (p.getKind() == ElementKind.ENUM) {
+      ExecutableType t = (ExecutableType) e.asType();
+      if (name.equals("values")) {
+        if (t.getParameterTypes().isEmpty()) {
+          return null;
+        }
+      } else if (name.equals("valueOf")) {
+        List<TypeMirror> valueOfParameterTypes =
+            Collections.singletonList(
+                utils.elementUtils
+                .getTypeElement("java.lang.String").asType());
+        if (t.getParameterTypes().equals(valueOfParameterTypes)) {
+          return null;
+        }
+      }
+    }
+
+    /* Create element; decide if constructor or not. */
+    if (name.toString().equals("<init>")) {
+      exec = new MethodModel();
+    } else {
+      exec = new MethodModel(ElementKind.METHOD, name,
+                             utils.getTypeNameForType(e.getReturnType()));
+    }
+    utils.copyModifiers(e, exec);
+
+    /* Add generic signature. */
+    List<? extends TypeParameterElement> genericTypes = e.getTypeParameters();
+    for (TypeParameterElement tp : genericTypes) {
+      exec.addTypeParameter(utils.getGenericTypeName(tp));
+    }
+
+    /* Add parameters. */
+    scan(e.getParameters(), exec);
+    exec.setVariadic(e.isVarArgs());
+
+    /* Add throws list. */
+    for (TypeMirror tt : e.getThrownTypes()) {
+      exec.addException(utils.getTypeNameForType(tt));
+    }
+
+    /* Add annotations. */
+    scanAnnotations(e, true, type.getName(), exec);
+
+    /* Register method. */
+    p.addEnclosedElement(exec);
+    addMethod(name, e, exec);
+
+    return null;
+  }
+
+  /**
+   * Adds an association to the method map.
+   */
+  protected void addMethod(String k, ExecutableElement e, MethodModel exec) {
+    ArrayList<ContractableMethod> list = methodMap.get(k);
+    if (list == null) {
+      list = new ArrayList<ContractableMethod>();
+      methodMap.put(k, list);
+    }
+    list.add(new ContractableMethod(e, exec));
+  }
+
+  /**
+   * Visits the superclass and interfaces of the specified
+   * TypeElement with a ContractExtensionBuilder.
+   */
+  protected void scanSuper(TypeElement e) {
+    TypeElement superElement =
+        (TypeElement) utils.typeUtils.asElement(e.getSuperclass());
+    if (superElement != null) {
+      superElement.accept(new ContractExtensionBuilder(), type);
+    }
+    for (TypeMirror iface : e.getInterfaces()) {
+      TypeElement ifaceElement =
+          (TypeElement) utils.typeUtils.asElement(iface);
+      ifaceElement.accept(new ContractExtensionBuilder(), type);
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/apt/TypeFactory.java b/src/com/google/java/contract/core/apt/TypeFactory.java
new file mode 100644
index 0000000..7bceb9c
--- /dev/null
+++ b/src/com/google/java/contract/core/apt/TypeFactory.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.apt;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.net.URLClassLoader;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * The TypeFactory creates {@link Type} objects from
+ * {@link TypeElement} objects. {@link Type} and all nested elements
+ * reflect the structure of Java types (classes, interfaces, methods,
+ * fields, annotations, ...) in Contracts for Java. Only the needed
+ * parts are reflected; unnecessary information is discarded.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+class TypeFactory {
+  protected URLClassLoader sourceDependencyLoader;
+
+  protected FactoryUtils utils;
+
+  @Requires("utils != null")
+  TypeFactory(FactoryUtils utils,
+              String sourceDependencyPath) {
+    sourceDependencyLoader = null;
+    if (sourceDependencyPath != null) {
+      sourceDependencyLoader =
+          JavaUtils.getLoaderForPath(sourceDependencyPath);
+    }
+
+    this.utils = utils;
+  }
+
+  /**
+   * Returns a {@link TypeModel} instance representing the specified
+   * {@link TypeElement}.
+   */
+  @Requires({
+    "element != null",
+    "diagnosticManager != null"
+  })
+  @Ensures({
+    "result != null",
+    "result.getName().getQualifiedName()" +
+        ".equals(element.getQualifiedName().toString())"
+  })
+  TypeModel createType(TypeElement element,
+                       DiagnosticManager diagnosticManager) {
+    String name = utils.elementUtils.getBinaryName(element)
+        .toString().replace('.', '/');
+    TypeBuilder visitor =
+        new TypeBuilder(utils, sourceDependencyLoader, diagnosticManager);
+    element.accept(visitor, null);
+    return visitor.getType();
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ClassName.java b/src/com/google/java/contract/core/model/ClassName.java
new file mode 100644
index 0000000..fb2542f
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ClassName.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.util.Predicate;
+
+/**
+ * A class name. This class supports the following formats:
+ *
+ * <ul>
+ * <li>simple: without package or nesting prefix;
+ * <li>(fully) qualified: with package prefix and enclosing classes
+ * separated with dots;
+ * <li>semi-qualified: with dot-separated package prefix (any '$' from
+ * class nesting remains);
+ * <li>declared: same as qualified, plus generic parameters;
+ * <li>binary: as found in bytecode (slash-separated package prefix).
+ * </ul>
+ *
+ * <p>For primitive and array types, use {@link TypeName}.
+ *
+ * <p>Anonymous classes do not have a proper name, and so cannot be
+ * designated by objects of this class.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "isSimpleName(getSimpleName())",
+  "isQualifiedName(getQualifiedName())",
+  "isQualifiedName(getSemiQualifiedName())",
+  "isBinaryName(getBinaryName())"
+})
+public class ClassName extends TypeName {
+  protected String simpleName;
+  protected String qualifiedName;
+  protected String semiQualifiedName;
+  protected String binaryName;
+
+  /**
+   * Constructs a new ClassName from its binary name. Other forms are
+   * inferred. The resulting class name is not generic (has no generic
+   * parameter).
+   */
+  @Requires("isBinaryName(binaryName)")
+  @Ensures("binaryName.equals(getBinaryName())")
+  public ClassName(String binaryName) {
+    this.binaryName = binaryName;
+    simpleName = null;
+    inferSemiQualifiedName();
+    inferQualifiedName();
+    inferSimpleName();
+    declaredName = qualifiedName;
+  }
+
+  /**
+   * Constructs a new ClassName from its binary and declared
+   * names. Other forms are inferred. The binary and declared names
+   * must represent the same type.
+   */
+  @Requires({
+    "isBinaryName(binaryName)",
+    "declaredName != null"
+  })
+  @Ensures({
+    "binaryName.equals(getBinaryName())",
+    "declaredName.equals(getDeclaredName())"
+  })
+  public ClassName(String binaryName, String declaredName) {
+    this.binaryName = binaryName;
+    this.declaredName = declaredName;
+    simpleName = null;
+    inferSemiQualifiedName();
+    inferQualifiedName();
+    inferSimpleName();
+    assertDeclaredQualifiedMatch();
+  }
+
+  @Requires({
+    "binaryName != null",
+    "declaredName != null",
+    "simpleName != null",
+    "binaryName.endsWith(simpleName)"
+  })
+  @Ensures({
+    "binaryName.equals(getBinaryName())",
+    "declaredName.equals(getDeclaredName())",
+    "simpleName.equals(getSimpleName())"
+  })
+  public ClassName(String binaryName, String declaredName, String simpleName) {
+    this.binaryName = binaryName;
+    this.declaredName = declaredName;
+    this.simpleName = simpleName;
+    inferSemiQualifiedName();
+    inferQualifiedName();
+    assertDeclaredQualifiedMatch();
+  }
+
+  protected void assertDeclaredQualifiedMatch() {
+    if (!declaredName.replaceAll("<[^.]*>", "").startsWith(qualifiedName)) {
+      throw new IllegalArgumentException(
+          "declared name '" + declaredName
+          + "' does not match qualified name '" + qualifiedName + "'");
+    }
+  }
+
+  public String getSimpleName() {
+    return simpleName;
+  }
+
+  /**
+   * Returns the relative component of {@code pathName}.
+   *
+   * @param pathName a dot-separated path
+   */
+  @Requires("pathName != null")
+  @Ensures("result != null")
+  public static String getRelativeName(String pathName) {
+    int lastSep = pathName.lastIndexOf('.');
+    if (lastSep == -1) {
+      return pathName;
+    } else {
+      return pathName.substring(lastSep + 1);
+    }
+  }
+
+  /**
+   * Returns the package component of {@code pathName}.
+   *
+   * @param pathName a dot-separated path
+   */
+  @Requires("pathName != null")
+  @Ensures("result != null")
+  public static String getPackageName(String pathName) {
+    int lastSep = pathName.lastIndexOf('.');
+    if (lastSep == -1) {
+      return "";
+    } else {
+      return pathName.substring(0, lastSep);
+    }
+  }
+
+  public String getQualifiedName() {
+    return qualifiedName;
+  }
+
+  public String getSemiQualifiedName() {
+    return semiQualifiedName;
+  }
+
+  public String getBinaryName() {
+    return binaryName;
+  }
+
+  private void inferSemiQualifiedName() {
+    semiQualifiedName = binaryName.replace('/', '.');
+  }
+
+  private void inferQualifiedName() {
+    if (simpleName == null) {
+      qualifiedName = semiQualifiedName.replace('$', '.');
+    } else {
+      int prefixLength = semiQualifiedName.length() - simpleName.length();
+      String prefix = semiQualifiedName.substring(0, prefixLength);
+      qualifiedName = prefix.replace('$', '.') + simpleName;
+    }
+  }
+
+  private void inferSimpleName() {
+    int i = qualifiedName.lastIndexOf('.');
+    if (i == -1) {
+      simpleName = qualifiedName;
+    } else {
+      simpleName = qualifiedName.substring(i + 1);
+    }
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return obj instanceof ClassName
+        && binaryName.equals(((ClassName) obj).binaryName)
+        && declaredName.equals(((ClassName) obj).declaredName);
+  }
+
+  @Override
+  public int hashCode() {
+    return binaryName.hashCode() ^ declaredName.hashCode();
+  }
+
+  /**
+   * Returns {@code true} if {@code name} is <em>syntactically</em> a
+   * valid simple name.
+   */
+  public static boolean isSimpleName(String name) {
+    if (name == null || name.isEmpty()) {
+      return false;
+    }
+    if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+      return false;
+    }
+    int len = name.length();
+    for (int i = 1; i < len; ++i) {
+      if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  protected static final Predicate<String> IS_SIMPLE_NAME =
+      new Predicate<String>() {
+    @Override
+    public boolean apply(String name) {
+      return isSimpleName(name);
+    }
+  };
+
+  public static Predicate<String> isSimpleName() {
+    return IS_SIMPLE_NAME;
+  }
+
+  /**
+   * Returns {@code true} if {@code name} is <em>syntactically</em> a
+   * valid qualified name.
+   *
+   * <p>Note: there is no syntactical difference between
+   * semi-qualified and fully-qualified names.
+   */
+  @Ensures("result == isBinaryName(name.replace('.', '/'))")
+  public static boolean isQualifiedName(String name) {
+    if (name == null || name.isEmpty()) {
+      return false;
+    }
+    String[] parts = name.split("\\.");
+    for (String part : parts) {
+      if (!isSimpleName(part)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private static final Predicate<String> IS_QUALIFIED_NAME =
+      new Predicate<String>() {
+    @Override
+    public boolean apply(String name) {
+      return isQualifiedName(name);
+    }
+  };
+
+  public static Predicate<String> isQualifiedName() {
+    return IS_QUALIFIED_NAME;
+  }
+
+  /**
+   * Returns {@code true} if {@code name} is <em>syntactically</em> a
+   * valid qualified name followed by the two characters {@code .*}.
+   */
+  public static boolean isStarQualifiedName(String name) {
+    return name != null
+        && name.endsWith(".*")
+        && isQualifiedName(name.substring(0, name.length() - 2));
+  }
+
+  /**
+   * Returns {@code true} if {@code name} is <em>syntactically</em> a
+   * valid binary name.
+   */
+  @Ensures("result == isQualifiedName(name.replace('/', '.'))")
+  public static boolean isBinaryName(String name) {
+    if (name == null || name.isEmpty()) {
+      return false;
+    }
+    String[] parts = name.split("/");
+    for (String part : parts) {
+      if (!isSimpleName(part)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private static final Predicate<String> IS_BINARY_NAME =
+      new Predicate<String>() {
+    @Override
+    public boolean apply(String name) {
+      return isBinaryName(name);
+    }
+  };
+
+  public static Predicate<String> isBinaryName() {
+    return IS_BINARY_NAME;
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ContractAnnotationModel.java b/src/com/google/java/contract/core/model/ContractAnnotationModel.java
new file mode 100644
index 0000000..424656e
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ContractAnnotationModel.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A model element representing one of the com.google.java.contract.* annotations.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at AllowUnusedImport({ Iterables.class, Predicates.class })
+ at Invariant({
+  "!isWeakVirtual() || isVirtual()",
+  "getValues() != null",
+  "!getValues().contains(null)",
+  "Iterables.all(getLineNumbers(), " +
+      "Predicates.or(Predicates.isNull(), Predicates.between(1L, null)))",
+  "getValues().size() == getLineNumbers().size()",
+  "getOwner() != null"
+})
+public class ContractAnnotationModel extends ElementModel {
+  /**
+   * {@code true} if this annotation is directly present on the
+   * annotated element, that is, it is not inherited through any of
+   * its interfaces or its superclass.
+   */
+  protected boolean primary;
+
+  /**
+   * {@code true} if this annotation denotes a virtual contract. A
+   * virtual contract is one that is inherited through the normal
+   * (virtual) class hierarchy, and not through an interface.
+   */
+  protected boolean virtual;
+
+  /**
+   * {@code true} if this annotation denotes a contract that is
+   * virtual but does not require a stub to be generated.
+   */
+  protected boolean weakVirtual;
+
+  /**
+   * The name of the owner type of this annotation, from which it is
+   * inherited.
+   */
+  protected ClassName owner;
+
+  /**
+   * The return type of the method contracted by this annotation; it
+   * is required for stubbing since return types may change
+   * covariantly with subtyping in Java.
+   */
+  protected TypeName returnType;
+
+  /**
+   * The values of this annotation. These are assertion expressions,
+   * as strings.
+   */
+  protected List<String> values;
+
+  /**
+   * The line numbers associated with the values of this expression,
+   * in the original source file (each line number may be
+   * {@code null}).
+   */
+  protected List<Long> lineNumbers;
+
+  /**
+   * Constructs a new ContractAnnotationModel.
+   *
+   * @param kind the kind of this element
+   * @param primary whether the annotation is directly present on the
+   * annotated element
+   * @param virtual {@code true} if the contract introduced by this
+   * annotation requires a stub
+   * @param owner the name of the class where this annotation is
+   * inherited from
+   * @param returnType the return type of the contracted method,
+   * if any
+   */
+  @Requires({
+    "kind != null",
+    "owner != null",
+    "kind.isSourceAnnotation()"
+  })
+  public ContractAnnotationModel(ElementKind kind, boolean primary,
+                                 boolean virtual, ClassName owner,
+                                 TypeName returnType) {
+    super(kind, "<@" + kind.name() + ">");
+    this.primary = primary;
+    this.virtual = virtual;
+    weakVirtual = false;
+    this.owner = owner;
+    this.returnType = returnType;
+    values = new ArrayList<String>();
+    lineNumbers = new ArrayList<Long>();
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  public ContractAnnotationModel(ContractAnnotationModel that) {
+    super(that);
+    primary = that.primary;
+    virtual = that.virtual;
+    weakVirtual = that.weakVirtual;
+    owner = that.owner;
+    returnType = that.returnType;
+    values = new ArrayList<String>(that.values);
+    lineNumbers = new ArrayList<Long>(that.lineNumbers);
+  }
+
+  @Override
+  public ContractAnnotationModel clone() {
+    return new ContractAnnotationModel(this);
+  }
+
+  public boolean isPrimary() {
+    return primary;
+  }
+
+  public boolean isVirtual() {
+    return virtual;
+  }
+
+  public boolean isWeakVirtual() {
+    return weakVirtual;
+  }
+
+  public void setWeakVirtual(boolean weakVirtual) {
+    this.weakVirtual = weakVirtual;
+  }
+
+  public ClassName getOwner() {
+    return owner;
+  }
+
+  public TypeName getReturnType() {
+    return returnType;
+  }
+
+  public List<String> getValues() {
+    return Collections.unmodifiableList(values);
+  }
+
+  public List<Long> getLineNumbers() {
+    return Collections.unmodifiableList(lineNumbers);
+  }
+
+  @Ensures({
+    "getValues().isEmpty()",
+    "getLineNumbers().isEmpty()"
+  })
+  public void clearValues() {
+    values.clear();
+    lineNumbers.clear();
+  }
+
+  @Requires("value != null")
+  @Ensures({
+    "getValues().size() == old(getValues().size()) + 1",
+    "getValues().contains(value.replace('\\r', ' ').replace('\\n', ' '))",
+    "getLineNumbers().size() == old(getLineNumbers().size()) + 1",
+    "getLineNumbers().contains(lineNumber)"
+  })
+  public void addValue(String value, Long lineNumber) {
+    values.add(value.replace('\r', ' ').replace('\n', ' '));
+    lineNumbers.add(lineNumber);
+  }
+
+  /**
+   * Returns {@code true} if the specified argument is equal to this
+   * object. Two ContractAnnotationModel objects are equal if they
+   * are of the same kind and have the same values.
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof ContractAnnotationModel)) {
+      return false;
+    }
+
+    ContractAnnotationModel annotation = (ContractAnnotationModel) obj;
+    return annotation.getKind() == getKind()
+        && annotation.getValues().equals(getValues());
+  }
+
+  @Override
+  public void accept(ElementVisitor visitor) {
+    visitor.visitContractAnnotation(this);
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ContractKind.java b/src/com/google/java/contract/core/model/ContractKind.java
new file mode 100644
index 0000000..c3c5ea7
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ContractKind.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+/**
+ * The kind of a contract method. This information is at the bytecode
+ * level. There are more contract method kinds than there are
+ * annotations; some of them, such as {@link #OLD} and
+ * {@link SIGNAL_OLD} are used for internal purposes.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public enum ContractKind {
+  /**
+   * A precondition contract method, which evaluates all direct
+   * (non-inherited) preconditions of the target method.
+   */
+  PRE,
+
+  /**
+   * A postcondition contract method, which evaluates all direct
+   * (non-inherited) postconditions of the target method.
+   */
+  POST,
+
+  /**
+   * An exceptional postcondition contract method, which evaluates all
+   * direct (non-inherited) exceptional postconditions of the target
+   * method.
+   */
+  SIGNAL,
+
+  /**
+   * An invariant contract method, which evaluates all direct
+   * (non-inherited) invariants of the target class.
+   */
+  INVARIANT,
+
+  /**
+   * An old value contract method, which computes one old value
+   * expression for the corresponding postcondition contract method.
+   */
+  OLD,
+
+  /**
+   * An exceptional old value contract method, which computes one old
+   * value expression for the corresponding exceptional postcondition
+   * contract method.
+   */
+  SIGNAL_OLD,
+
+  /**
+   * A synthetic access method, generated by the Java compiler, used
+   * in contract methods.
+   */
+  ACCESS,
+
+  /**
+   * A contract helper, for indirect contract evaluation.
+   *
+   * @see ContractCreator
+   */
+  HELPER;
+
+  /**
+   * Returns {@code true} if this kind denotes a contract method that
+   * applies to a class.
+   */
+  @Ensures("result == (!isMethodContract() && !isHelperContract())")
+  public boolean isClassContract() {
+    switch (this) {
+      case INVARIANT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /**
+   * Returns {@code true} if this kind denotes a contract method that
+   * applies to a method.
+   */
+  @Ensures("result == (!isClassContract() && !isHelperContract())")
+  public boolean isMethodContract() {
+    switch (this) {
+      case PRE:
+      case POST:
+      case SIGNAL:
+      case OLD:
+      case SIGNAL_OLD:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /**
+   * Returns {@code true} if this kind denotes a helper contract
+   * method, called by other contract methods.
+   */
+  @Ensures("result == (!isClassContract() && !isMethodContract())")
+  public boolean isHelperContract() {
+    return !isClassContract() && !isMethodContract();
+  }
+
+  /**
+   * Returns {@code true} if this kind denotes a postcondition (normal
+   * or exceptional).
+   */
+  @Ensures({
+    "!result || isMethodContract()",
+    "!(result && isOld())"
+  })
+  public boolean isPostcondition() {
+    switch (this) {
+      case POST:
+      case SIGNAL:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /**
+   * Returns {@code true} if this kind denotes a method contract old
+   * computing method values.
+   */
+  @Ensures({
+    "!result || isMethodContract()",
+    "!(result && isPostcondition())"
+  })
+  public boolean isOld() {
+    switch (this) {
+      case OLD:
+      case SIGNAL_OLD:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /**
+   * Returns the kind of the old value contract methods computing old
+   * values for this kind.
+   */
+  @Requires("isPostcondition()")
+  public ContractKind getOldKind() {
+    switch (this) {
+      case POST:
+        return OLD;
+      case SIGNAL:
+        return SIGNAL_OLD;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  public boolean hasNameSpace() {
+    return this != HELPER;
+  }
+
+  /**
+   * Returns the name space used when generating contract method names
+   * for this kind.
+   */
+  @Requires("hasNameSpace()")
+  @Ensures("ClassName.isSimpleName(result)")
+  public String getNameSpace() {
+    switch (this) {
+      case PRE:
+        return "com$google$java$contract$P";
+      case POST:
+        return "com$google$java$contract$Q";
+      case SIGNAL:
+        return "com$google$java$contract$E";
+      case INVARIANT:
+        return "com$google$java$contract$I";
+      case OLD:
+        return "com$google$java$contract$QO";
+      case SIGNAL_OLD:
+        return "com$google$java$contract$EO";
+      case ACCESS:
+        return "access";
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * Returns the name space used when generating helper contract
+   * method names for this kind.
+   */
+  @Requires("!isHelperContract()")
+  @Ensures("ClassName.isSimpleName(result)")
+  public String getHelperNameSpace() {
+    switch (this) {
+      case PRE:
+        return "com$google$java$contract$PH";
+      case POST:
+        return "com$google$java$contract$QH";
+      case SIGNAL:
+        return "com$google$java$contract$EH";
+      case INVARIANT:
+        return "com$google$java$contract$IH";
+      case OLD:
+        return "com$google$java$contract$QOH";
+      case SIGNAL_OLD:
+        return "com$google$java$contract$EOH";
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * Returns the variance of this kind, or {@code null} if not
+   * applicable.
+   */
+  public ContractVariance getVariance() {
+    switch (this) {
+      case PRE:
+        return ContractVariance.CONTRAVARIANT;
+      case POST:
+      case SIGNAL:
+      case INVARIANT:
+        return ContractVariance.COVARIANT;
+      default:
+        return null;
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ContractMethodModel.java b/src/com/google/java/contract/core/model/ContractMethodModel.java
new file mode 100644
index 0000000..7161cca
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ContractMethodModel.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.Elements;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+
+/**
+ * A model element representing a contract method. Contrary to other
+ * methods, contract methods are not mocked and the model accounts for
+ * the implementation code. This code is stored in text form.
+ */
+ at Invariant({
+  "getContractKind() != null",
+  "getId() >= -1",
+  "getStatements() != null",
+  "!getStatements().contains(null)",
+  "!getContractKind().isClassContract() || getContractedMethod() == null",
+  "!getContractKind().isMethodContract() || getContractedMethod() != null"
+})
+public class ContractMethodModel extends MethodModel {
+  private static final ClassName CONTRACT_SIGNATURE_CLASS =
+      new ClassName("com/google/java/contract/core/ContractMethodSignature");
+
+  /**
+   * The kind of contract this method implements.
+   */
+  protected ContractKind contractKind;
+
+  /**
+   * The ID of this contract method.
+   */
+  protected int id;
+
+  /**
+   * The body of this method, as strings of code.
+   */
+  protected List<String> statements;
+
+  /**
+   * A fixed prologue.
+   */
+  protected String prologue;
+
+  /**
+   * A fixed epilogue.
+   */
+  protected String epilogue;
+
+  /**
+   * The contracted method this contract applies to, or {@code null}
+   * if this is a class-wide contract.
+   */
+  protected MethodModel contractedMethod;
+
+  /**
+   * The line numbers associated with the original source annotation
+   * that specifies this contract.
+   */
+  protected List<Long> lineNumbers;
+
+  /**
+   * Constructs a new ContractMethodModel.
+   *
+   * @param kind the kind of this contract
+   * @param name the name of this contract method
+   * @param returnType the return type of this method
+   * @param contracted the contracted method, if any
+   */
+  @Requires({
+    "kind != null",
+    "name != null",
+    "returnType != null",
+    "!kind.isClassContract() || contracted == null"
+  })
+  public ContractMethodModel(ContractKind kind, String name,
+                             TypeName returnType, MethodModel contracted) {
+    super(ElementKind.CONTRACT_METHOD, name, returnType);
+
+    if (contracted != null) {
+      typeParameters = new ArrayList<TypeName>(contracted.getTypeParameters());
+      Elements.copyParameters(this, contracted.getParameters());
+      modifiers = EnumSet.copyOf(contracted.getModifiers());
+    }
+    fixCommonModifiers();
+
+    contractKind = kind;
+    id = -1;
+
+    statements = new ArrayList<String>();
+    prologue = null;
+    epilogue = null;
+
+    contractedMethod = contracted;
+    lineNumbers = null;
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  public ContractMethodModel(ContractMethodModel that) {
+    super(that);
+
+    contractKind = that.contractKind;
+    id = that.id;
+
+    statements = new ArrayList<String>(that.statements);
+    prologue = that.prologue;
+    epilogue = that.epilogue;
+
+    contractedMethod = that.contractedMethod;
+    lineNumbers = that.lineNumbers;
+  }
+
+  @Override
+  public ContractMethodModel clone() {
+    return new ContractMethodModel(this);
+  }
+
+  /**
+   * Removes commonly undesirable modifiers that might have been
+   * inherited.
+   */
+  private void fixCommonModifiers() {
+    removeModifier(ElementModifier.ABSTRACT);
+    removeModifier(ElementModifier.TRANSIENT);
+  }
+
+  public ContractKind getContractKind() {
+    return contractKind;
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(int id) {
+    this.id = id;
+  }
+
+  public MethodModel getContractedMethod() {
+    return contractedMethod;
+  }
+
+  public List<Long> getLineNumbers() {
+    return lineNumbers;
+  }
+
+  @Ensures("lineNumbers == getLineNumbers()")
+  public void setLineNumbers(List<Long> lineNumbers) {
+    this.lineNumbers = lineNumbers;
+  }
+
+  @Ensures("result != null")
+  public String getCode() {
+    StringBuilder buffer = new StringBuilder();
+    if (prologue != null) {
+      buffer.append(prologue);
+    }
+    for (String stmt : statements) {
+      buffer.append(stmt);
+    }
+    if (epilogue != null) {
+      buffer.append(epilogue);
+    }
+    return buffer.toString();
+  }
+
+  public List<String> getStatements() {
+    return Collections.unmodifiableList(statements);
+  }
+
+  public String getPrologue() {
+    return prologue;
+  }
+
+  @Ensures("getPrologue().equals(prologue)")
+  public void setPrologue(String prologue) {
+    this.prologue = prologue;
+  }
+
+  public String getEpilogue() {
+    return epilogue;
+  }
+
+  @Ensures("getEpilogue().equals(epilogue)")
+  public void setEpilogue(String epilogue) {
+    this.epilogue = epilogue;
+  }
+
+  @Ensures("getStatements().isEmpty()")
+  public void clearStatements() {
+    statements.clear();
+  }
+
+  @Requires("stmt != null")
+  @Ensures({
+    "getStatements().size() == old(getStatements().size()) + 1",
+    "getStatements().contains(stmt)"
+  })
+  public void addStatement(String stmt) {
+    statements.add(stmt);
+  }
+
+  @Override
+  public void accept(ElementVisitor visitor) {
+    visitor.visitContractMethod(this);
+  }
+
+  @Override
+  public EnumSet<ElementKind> getAllowedEnclosedKinds() {
+    EnumSet<ElementKind> allowed =
+        EnumSet.of(ElementKind.CONTRACT_SIGNATURE);
+    allowed.addAll(super.getAllowedEnclosedKinds());
+    return allowed;
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ContractVariance.java b/src/com/google/java/contract/core/model/ContractVariance.java
new file mode 100644
index 0000000..819d2a0
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ContractVariance.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+/**
+ * The variance of a kind of contract. Contracts are either
+ * contravariant (preconditions), covariant (postconditions and
+ * invariants), or have no variance (represented by {@code null}).
+ *
+ * <p>Multiple contravariant contracts should be combined using the
+ * <em>or</em> combinator. Multiple covariant contracts should be
+ * combined using the <em>and</em> combinator. Contracts that have no
+ * variance should not be combined.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public enum ContractVariance {
+  /**
+   * A contravariant contract.
+   */
+  CONTRAVARIANT,
+
+  /**
+   * A covariant contract.
+   */
+  COVARIANT;
+}
diff --git a/src/com/google/java/contract/core/model/ElementKind.java b/src/com/google/java/contract/core/model/ElementKind.java
new file mode 100644
index 0000000..d1ac5f0
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ElementKind.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Requires;
+
+/**
+ * The kind of an {@link Element}.
+ */
+public enum ElementKind {
+  /*
+   * Source elements.
+   */
+
+  /**
+   * A source file.
+   */
+  SOURCE,
+
+  /**
+   * A class.
+   */
+  CLASS,
+
+  /**
+   * An interface.
+   */
+  INTERFACE,
+
+  /**
+   * An annotation.
+   */
+  ANNOTATION_TYPE,
+
+  /**
+   * An enum.
+   */
+  ENUM,
+
+  /**
+   * An enum constant.
+   */
+  CONSTANT,
+
+  /**
+   * A field. Mocked in output.
+   */
+  FIELD,
+
+  /**
+   * A method that is not a constructor. Mocked in output.
+   */
+  METHOD,
+
+  /**
+   * A constructor. Mocked in output.
+   */
+  CONSTRUCTOR,
+
+  /**
+   * A method parameter.
+   */
+  PARAMETER,
+
+  /**
+   * An @Invariant annotation.
+   */
+  INVARIANT,
+
+  /**
+   * An @Requires annotation. Source-only, not present in output.
+   */
+  REQUIRES,
+
+  /**
+   * An @Ensures annotation. Source-only, not present in output.
+   */
+  ENSURES,
+
+  /**
+   * An @ThrowEnsures annotation. Source-only, not present in output.
+   */
+  THROW_ENSURES,
+
+  /*
+   * Output elements.
+   */
+
+  /**
+   * An @ContractMethodSignature annotation.
+   */
+  CONTRACT_SIGNATURE,
+
+  /**
+   * A contract method.
+   */
+  CONTRACT_METHOD,
+
+  /**
+   * A mock contract method.
+   */
+  CONTRACT_MOCK;
+
+  public boolean isType() {
+    switch (this) {
+      case CLASS:
+      case ENUM:
+      case INTERFACE:
+      case ANNOTATION_TYPE:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  public boolean isMember() {
+    switch (this) {
+      case FIELD:
+      case METHOD:
+      case CONSTRUCTOR:
+      case CONTRACT_METHOD:
+      case CONTRACT_MOCK:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Requires("isMember()")
+  public boolean isMock() {
+    switch (this) {
+      case METHOD:
+      case CONSTRUCTOR:
+      case CONTRACT_MOCK:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Requires("isMember()")
+  public boolean isContract() {
+    return !isMock();
+  }
+
+  public boolean isAnnotation() {
+    switch (this) {
+      case INVARIANT:
+      case REQUIRES:
+      case ENSURES:
+      case THROW_ENSURES:
+      case CONTRACT_SIGNATURE:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  public boolean isInterfaceType() {
+    switch(this) {
+      case INTERFACE:
+      case ANNOTATION_TYPE:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  public boolean isSourceAnnotation() {
+    switch (this) {
+      case INVARIANT:
+      case REQUIRES:
+      case ENSURES:
+      case THROW_ENSURES:
+        return true;
+      default:
+        return false;
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ElementModel.java b/src/com/google/java/contract/core/model/ElementModel.java
new file mode 100644
index 0000000..29279cf
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ElementModel.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicate;
+import com.google.java.contract.util.Predicates;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+
+/**
+ * An abstract model element.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at AllowUnusedImport({ Iterables.class, Predicates.class })
+ at Invariant({
+  "getEnclosingElement() == null " +
+      "|| getEnclosingElement().getEnclosedElements().contains(this)",
+  "Iterables.all(getEnclosedElements(), isValidEnclosedElement())",
+  "getKind() != null",
+  "getSimpleName() != null"
+})
+public abstract class ElementModel implements Cloneable {
+  /**
+   * The kind of this element.
+   */
+  protected ElementKind kind;
+
+  /**
+   * The simple name of this element. The simple name is the relative
+   * identifier used to refer to this element in source code.
+   *
+   * <p>This name must be kept synchronized with other forms, if any.
+   */
+  protected String simpleName;
+
+  /**
+   * The parent element of this element.
+   */
+  protected ElementModel enclosingElement;
+
+  /**
+   * The child elements of this element. Each kind refines its own
+   * enclosing--enclosed relationship with other kinds.
+   *
+   * <p>This list must contain all enclosed elements but need not be
+   * the only such container. Specialized, partial subsets of enclosed
+   * elements, if any, must be kept synchronized with this field.
+   */
+  protected List<ElementModel> enclosedElements;
+
+  /**
+   * An object intended to hold information on the source of this
+   * model element.
+   */
+  protected Object sourceInfo;
+
+  /**
+   * Constructs a new ElementModel of the specified kind, with the
+   * specified simple name.
+   */
+  @Requires({
+    "kind != null",
+    "name != null"
+  })
+  protected ElementModel(ElementKind kind, String name) {
+    this.kind = kind;
+    simpleName = name;
+    enclosingElement = null;
+    enclosedElements = new ArrayList<ElementModel>();
+    sourceInfo = null;
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  protected ElementModel(ElementModel that) {
+    kind = that.kind;
+    simpleName = that.simpleName;
+    enclosingElement = null;
+    enclosedElements =
+        new ArrayList<ElementModel>(that.enclosedElements.size());
+    ArrayList<ElementModel> elements =
+        new ArrayList<ElementModel>(that.enclosedElements);
+    for (ElementModel element : elements) {
+      try {
+        addEnclosedElement(element.clone());
+      } catch (CloneNotSupportedException e) {
+        /*
+         * Not reached. Only abstract classes in the hierarchy will
+         * throw CloneNotSupportedException.
+         */
+      }
+    }
+    sourceInfo = that.sourceInfo;
+  }
+
+  @Override
+  @Ensures({
+    "result != null",
+    "result.getEnclosingElement() == null"
+  })
+  protected ElementModel clone() throws CloneNotSupportedException {
+    throw new CloneNotSupportedException();
+  }
+
+  public ElementKind getKind() {
+    return kind;
+  }
+
+  public List<? extends ElementModel> getEnclosedElements() {
+    return Collections.unmodifiableList(enclosedElements);
+  }
+
+  /**
+   * Adds a child element at the specified position in the enclosed
+   * element list. First, the added element is detached from its
+   * previous parent, if any.
+   */
+  @Requires({
+    "index >= 0",
+    "index <= element.getEnclosedElements().size()",
+    "isValidEnclosedElement(element)"
+  })
+  @Ensures("enclosedElements.contains(element)")
+  protected void addEnclosedElement(int index, ElementModel element) {
+    fixEnclosedElement(element);
+    enclosedElements.add(index, element);
+  }
+
+  /**
+   * Adds a child element to the enclosed element list. First, the
+   * added element is detached from its previous parent, if any.
+   */
+  @Requires("isValidEnclosedElement(element)")
+  @Ensures("getEnclosedElements().contains(element)")
+  public void addEnclosedElement(ElementModel element) {
+    fixEnclosedElement(element);
+    enclosedElements.add(element);
+  }
+
+  private void fixEnclosedElement(ElementModel element) {
+    if (element.enclosingElement != null) {
+      element.enclosingElement.removeEnclosedElement(element);
+    }
+    element.enclosingElement = this;
+  }
+
+  @Requires("isValidEnclosedElement(element)")
+  @Ensures("!getEnclosedElements().contains(element)")
+  public void removeEnclosedElement(ElementModel element) {
+    enclosedElements.remove(element);
+    element.enclosingElement = null;
+  }
+
+  public ElementModel getEnclosingElement() {
+    return enclosingElement;
+  }
+
+  @Requires("element == null || isValidEnclosedElement(element)")
+  @Ensures({
+    "element == getEnclosingElement()",
+    "element.getEnclosedElements().contains(this)"
+  })
+  public void setEnclosingElement(ElementModel element) {
+    element.addEnclosedElement(this);
+  }
+
+  public String getSimpleName() {
+    return simpleName;
+  }
+
+  public Object getSourceInfo() {
+    return sourceInfo;
+  }
+
+  public void setSourceInfo(Object info) {
+    sourceInfo = info;
+  }
+
+  /**
+   * Visits this element with the specified visitor.
+   */
+  @Requires("visitor != null")
+  public abstract void accept(ElementVisitor visitor);
+
+  /**
+   * Returns {@code true} if the specified argument is equal to this
+   * object. Two ElementModel are equal if they have the same simple
+   * name and their enclosing elements are equal.
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof ElementModel)) {
+      return false;
+    }
+
+    ElementModel element = (ElementModel) obj;
+    return element.getSimpleName().equals(getSimpleName())
+        && element.getEnclosingElement().equals(getEnclosingElement());
+  }
+
+  @Override
+  public int hashCode() {
+    return 31 * simpleName.hashCode() + getEnclosingElement().hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return simpleName;
+  }
+
+  /**
+   * Returns {@code true} if {@code element} can be added (as an
+   * enclosed element) to this element.
+   */
+  public boolean isValidEnclosedElement(ElementModel element) {
+    return element != null
+        && getAllowedEnclosedKinds().contains(element.getKind());
+  }
+
+  private final Predicate<ElementModel> isValidEnclosedElementPredicate =
+      new Predicate<ElementModel>() {
+    @Override
+    public boolean apply(ElementModel element) {
+      return isValidEnclosedElement(element);
+    }
+  };
+
+  public Predicate<ElementModel> isValidEnclosedElement() {
+    return isValidEnclosedElementPredicate;
+  }
+
+  /**
+   * Reflectively returns the kinds of elements that are allowed as
+   * children of this element.
+   */
+  @Ensures("result != null")
+  public EnumSet<ElementKind> getAllowedEnclosedKinds() {
+    return EnumSet.noneOf(ElementKind.class);
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ElementModifier.java b/src/com/google/java/contract/core/model/ElementModifier.java
new file mode 100644
index 0000000..5eb21fa
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ElementModifier.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+import java.util.EnumSet;
+import java.util.Set;
+import javax.lang.model.element.Modifier;
+
+/**
+ * A Java declaration modifier. In general, modifiers can be applied
+ * to types, fields, and methods.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public enum ElementModifier {
+  /**
+   * The public modifier.
+   */
+  PUBLIC,
+
+  /**
+   * The protected modifier.
+   */
+  PROTECTED,
+
+  /**
+   * The package private modifier. This is the default visibility.
+   */
+  PACKAGE_PRIVATE,
+
+  /**
+   * The private modifier.
+   */
+  PRIVATE,
+
+  /**
+   * The modifier static.
+   */
+  STATIC,
+
+  /**
+   * The final modifier.
+   */
+  FINAL,
+
+  /**
+   * The volatile modifier.
+   */
+  VOLATILE,
+
+  /**
+   * The transient modifier .
+   */
+  TRANSIENT,
+
+  /**
+   * The abstract modifier.
+   */
+  ABSTRACT,
+
+  /**
+   * The synchronized modifier.
+   */
+  SYNCHRONIZED,
+
+  /**
+   * The native modifier.
+   */
+  NATIVE;
+
+  public boolean isVisibility() {
+    switch (this) {
+      case PUBLIC:
+      case PROTECTED:
+      case PACKAGE_PRIVATE:
+      case PRIVATE:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  @Requires("modifiers != null")
+  public static ElementModifier visibilityIn(
+      EnumSet<ElementModifier> modifiers) {
+    for (ElementModifier modifier : modifiers) {
+      if (modifier.isVisibility()) {
+        return modifier;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Converts a set of {@link Modifier} objects into a set of
+   * {@link ElementModifier} objects.
+   */
+  @Requires("modifiers != null")
+  @Ensures("result != null")
+  public static EnumSet<ElementModifier> forModifiers(
+      Set<? extends Modifier> modifiers){
+    EnumSet<ElementModifier> result = EnumSet.noneOf(ElementModifier.class);
+
+    if (!modifiers.contains(Modifier.PUBLIC)
+       && !modifiers.contains(Modifier.PROTECTED)
+       && !modifiers.contains(Modifier.PRIVATE)) {
+      result.add(ElementModifier.PACKAGE_PRIVATE);
+    }
+
+    for (Modifier modifier : modifiers) {
+      switch (modifier) {
+        case PUBLIC:
+          result.add(ElementModifier.PUBLIC);
+          break;
+        case PROTECTED:
+          result.add(ElementModifier.PROTECTED);
+          break;
+        case PRIVATE:
+          result.add(ElementModifier.PRIVATE);
+          break;
+        case STATIC:
+          result.add(ElementModifier.STATIC);
+          break;
+        case FINAL:
+          result.add(ElementModifier.FINAL);
+          break;
+        case VOLATILE:
+          result.add(ElementModifier.VOLATILE);
+          break;
+        case TRANSIENT:
+          result.add(ElementModifier.TRANSIENT);
+          break;
+        case ABSTRACT:
+          result.add(ElementModifier.ABSTRACT);
+          break;
+        case SYNCHRONIZED:
+          result.add(ElementModifier.SYNCHRONIZED);
+          break;
+        case NATIVE:
+          result.add(ElementModifier.NATIVE);
+          break;
+        default:
+          /* Unsupported modifier. */
+          break;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns the Java source code representation of this modifier, or
+   * the empty string if none.
+   */
+  @Override
+  public String toString() {
+    switch (this) {
+      case PUBLIC:
+      case PROTECTED:
+      case PRIVATE:
+      case STATIC:
+      case FINAL:
+      case VOLATILE:
+      case ABSTRACT:
+      case SYNCHRONIZED:
+        return name().toLowerCase();
+      default:
+        return "";
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/model/ElementVisitor.java b/src/com/google/java/contract/core/model/ElementVisitor.java
new file mode 100644
index 0000000..a4a1745
--- /dev/null
+++ b/src/com/google/java/contract/core/model/ElementVisitor.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Requires;
+
+/**
+ * A visitor of model elements.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+public interface ElementVisitor {
+  /**
+   * Visits a {@link TypeModel} object.
+   */
+  @Requires("type != null")
+  public void visitType(TypeModel type);
+
+  /**
+   * Visits a {@link VariableModel} object.
+   */
+  @Requires("variable != null")
+  public void visitVariable(VariableModel variable);
+
+  /**
+   * Visits an {@link MethodModel} object.
+   */
+  @Requires("method != null")
+  public void visitMethod(MethodModel method);
+
+  /**
+   * Visits a {@link ContractMethodModel} object.
+   */
+  @Requires("contract != null")
+  public void visitContractMethod(ContractMethodModel contract);
+
+  /**
+   * Visits a {@link ContractAnnotationModel} object.
+   */
+  @Requires("annotation != null")
+  public void visitContractAnnotation(ContractAnnotationModel annotation);
+}
diff --git a/src/com/google/java/contract/core/model/GenericElementModel.java b/src/com/google/java/contract/core/model/GenericElementModel.java
new file mode 100644
index 0000000..785bb52
--- /dev/null
+++ b/src/com/google/java/contract/core/model/GenericElementModel.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * An abstract model element representing an element that can accept
+ * type parameters.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "getTypeParameters() != null",
+  "!getTypeParameters().contains(null)"
+})
+public abstract class GenericElementModel extends QualifiedElementModel {
+  /**
+   * The list of type parameters of this type; empty if not a generic
+   * type.
+   */
+  protected List<TypeName> typeParameters;
+
+  /**
+   * Constructs a new TypeModel of the specified kind, with the
+   * specified name.
+   */
+  @Requires({
+    "kind != null",
+    "name != null"
+  })
+  protected GenericElementModel(ElementKind kind, String name) {
+    super(kind, name);
+    typeParameters = new ArrayList<TypeName>();
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  protected GenericElementModel(GenericElementModel that) {
+    super(that);
+    typeParameters = new ArrayList<TypeName>(that.typeParameters);
+  }
+
+  @Override
+  protected GenericElementModel clone() throws CloneNotSupportedException {
+    throw new CloneNotSupportedException();
+  }
+
+  public List<? extends TypeName> getTypeParameters() {
+    return Collections.unmodifiableList(typeParameters);
+  }
+
+  @Ensures("getTypeParameters().isEmpty()")
+  public void clearTypeParameters() {
+    typeParameters.clear();
+  }
+
+  @Requires("typeName != null")
+  @Ensures({
+    "getTypeParameters().size() == old(getTypeParameters().size()) + 1",
+    "getTypeParameters().contains(typeName)"
+  })
+  public void addTypeParameter(TypeName typeName) {
+    typeParameters.add(typeName);
+  }
+}
diff --git a/src/com/google/java/contract/core/model/HelperTypeModel.java b/src/com/google/java/contract/core/model/HelperTypeModel.java
new file mode 100644
index 0000000..9219ef3
--- /dev/null
+++ b/src/com/google/java/contract/core/model/HelperTypeModel.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.JavaUtils;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * A helper type, used to implement interface contracts.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class HelperTypeModel extends TypeModel {
+  /**
+   * Constructs a new HelperTypeModel for the interface type
+   * {@code original}.
+   */
+  @Requires({
+    "original != null",
+    "original.getKind() == ElementKind.INTERFACE"
+  })
+  public HelperTypeModel(TypeModel original) {
+    super(original);
+
+    kind = ElementKind.CLASS;
+
+    String oldQualifiedName = name.getQualifiedName();
+    String newQualifiedName = oldQualifiedName + JavaUtils.HELPER_CLASS_SUFFIX;
+    String newDeclaredName =
+        name.getDeclaredName().replace(oldQualifiedName, newQualifiedName);
+    name = new ClassName(name.getBinaryName() + JavaUtils.HELPER_CLASS_SUFFIX,
+                         newDeclaredName,
+                         name.getSimpleName() + JavaUtils.HELPER_CLASS_SUFFIX);
+    simpleName = name.getSimpleName();
+
+    interfaces = Collections.singleton(original.getName());
+    superArguments = Collections.emptyList();
+
+    Iterator<ElementModel> iter = enclosedElements.iterator();
+    while (iter.hasNext()) {
+      if (iter.next().getKind().isType()) {
+        iter.remove();
+      }
+    }
+  }
+
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  public HelperTypeModel(HelperTypeModel that) {
+    super(that);
+  }
+
+  @Override
+  public HelperTypeModel clone() {
+    return new HelperTypeModel(this);
+  }
+}
diff --git a/src/com/google/java/contract/core/model/MethodModel.java b/src/com/google/java/contract/core/model/MethodModel.java
new file mode 100644
index 0000000..9b6d302
--- /dev/null
+++ b/src/com/google/java/contract/core/model/MethodModel.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.Elements;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A model element representing a method.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "getExceptions() != null",
+  "isConstructor() == (returnType == null)"
+})
+public class MethodModel extends GenericElementModel {
+  /**
+   * The list of exceptions that can be thrown by this method.
+   */
+  protected Set<TypeName> exceptions;
+
+  /**
+   * The return type of this method, or {@code null} if this is a
+   * constructor.
+   */
+  protected TypeName returnType;
+
+  /**
+   * Whether this method accepts variable-length argument lists.
+   */
+  protected boolean variadic;
+
+  /**
+   * Constructs a new MethodModel of the specified kind, which is not
+   * a constructor, with the specified name and return type.
+   */
+  @Requires({
+    "kind != null",
+    "kind.isMember() && kind != ElementKind.FIELD",
+    "kind != ElementKind.CONSTRUCTOR",
+    "name != null",
+    "returnType != null"
+  })
+  public MethodModel(ElementKind kind, String name, TypeName returnType) {
+    super(kind, name);
+    exceptions = new HashSet<TypeName>();
+    this.returnType = returnType;
+    variadic = false;
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  public MethodModel(MethodModel that) {
+    super(that);
+    exceptions = new HashSet<TypeName>(that.exceptions);
+    returnType = that.returnType;
+    variadic = false;
+  }
+
+  @Override
+  public MethodModel clone() {
+    return new MethodModel(this);
+  }
+
+  /**
+   * Constructs a new constructor model.
+   */
+  public MethodModel() {
+    super(ElementKind.CONSTRUCTOR, "<init>");
+    exceptions = new HashSet<TypeName>();
+    returnType = null;
+    variadic = false;
+  }
+
+  public Set<? extends TypeName> getExceptions() {
+    return Collections.unmodifiableSet(exceptions);
+  }
+
+  @Requires("exception != null")
+  @Ensures("getExceptions().contains(exception)")
+  public void addException(TypeName exception) {
+    exceptions.add(exception);
+  }
+
+  @Requires("exception != null")
+  @Ensures("!getExceptions().contains(exception)")
+  public void removeException(TypeName exception) {
+    exceptions.remove(exception);
+  }
+
+  @Requires("!isConstructor()")
+  @Ensures("result != null")
+  public TypeName getReturnType() {
+    return returnType;
+  }
+
+  @Requires({
+    "!isConstructor()",
+    "type != null"
+  })
+  public void setReturnType(TypeName type) {
+    returnType = type;
+  }
+
+  public boolean isVariadic() {
+    return variadic;
+  }
+
+  public void setVariadic(boolean variadic) {
+    this.variadic = variadic;
+  }
+
+  public boolean isConstructor() {
+    return kind == ElementKind.CONSTRUCTOR;
+  }
+
+  @Ensures("result != null")
+  public List<? extends VariableModel> getParameters() {
+    return Elements.filter(getEnclosedElements(), VariableModel.class,
+                           ElementKind.PARAMETER);
+  }
+
+  @Requires({
+    "param != null",
+    "param.getKind() == ElementKind.PARAMETER"
+  })
+  @Ensures({
+    "getEnclosedElements().contains(param)",
+    "getParameters().contains(param)"
+  })
+  public void addParameter(VariableModel param) {
+    addEnclosedElement(param);
+  }
+
+  @Requires({
+    "param != null",
+    "param.getKind() == ElementKind.PARAMETER"
+  })
+  @Ensures({
+    "!getEnclosedElements().contains(param)",
+    "!getParameters().contains(param)"
+  })
+  public void removeParameter(VariableModel param) {
+    removeEnclosedElement(param);
+  }
+
+  @Override
+  public void accept(ElementVisitor visitor) {
+    visitor.visitMethod(this);
+  }
+
+  @Override
+  public EnumSet<ElementKind> getAllowedEnclosedKinds() {
+    EnumSet<ElementKind> allowed =
+        EnumSet.of(ElementKind.PARAMETER,
+                   ElementKind.REQUIRES,
+                   ElementKind.ENSURES,
+                   ElementKind.THROW_ENSURES);
+    allowed.addAll(super.getAllowedEnclosedKinds());
+    return allowed;
+  }
+
+  /**
+   * Returns {@code true} if the specified argument is equal to this
+   * object. Two MethodModel objects are equal if they have the same
+   * simple name and parameter types and their enclosing elements are
+   * equal. Equality for MethodModel objects is loose: two methods can
+   * be <em>unequal</em> and still conflict with one another; this
+   * implementation only guarantees that objects representing
+   * different methods will not be compared equal.
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof MethodModel)) {
+      return false;
+    }
+
+    MethodModel method = (MethodModel) obj;
+    if (!method.getSimpleName().equals(getSimpleName())) {
+      return false;
+    }
+    List<? extends VariableModel> params = getParameters();
+    List<? extends VariableModel> others = method.getParameters();
+    if (params.size() != others.size()) {
+      return false;
+    }
+    Iterator<? extends VariableModel> itParams = params.iterator();
+    Iterator<? extends VariableModel> itOthers = others.iterator();
+    while (itParams.hasNext()) {
+      if (!itParams.next().getType().equals(itOthers.next().getType())) {
+        return false;
+      }
+    }
+    return method.getEnclosingElement().equals(getEnclosingElement());
+  }
+}
diff --git a/src/com/google/java/contract/core/model/QualifiedElementModel.java b/src/com/google/java/contract/core/model/QualifiedElementModel.java
new file mode 100644
index 0000000..8ca7dd4
--- /dev/null
+++ b/src/com/google/java/contract/core/model/QualifiedElementModel.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.util.EnumSet;
+
+/**
+ * An abstract model element that can be qualified with modifiers.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("getModifiers() != null")
+public abstract class QualifiedElementModel extends ElementModel {
+  /**
+   * The modifiers that apply to this element.
+   */
+  protected EnumSet<ElementModifier> modifiers;
+
+  /**
+   * Constructs a new QualifiedElementModel of the specified kind,
+   * with the specified simple name.
+   */
+  @Requires({
+    "kind != null",
+    "name != null"
+  })
+  protected QualifiedElementModel(ElementKind kind, String name) {
+    super(kind, name);
+    modifiers = EnumSet.noneOf(ElementModifier.class);
+  }
+
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  protected QualifiedElementModel(QualifiedElementModel that) {
+    super(that);
+    modifiers = EnumSet.copyOf(that.modifiers);
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Override
+  protected QualifiedElementModel clone() throws CloneNotSupportedException {
+    throw new CloneNotSupportedException();
+  }
+
+  public EnumSet<ElementModifier> getModifiers() {
+    return modifiers;
+  }
+
+  /**
+   * Adds a modifier to this element. This method ensures that exactly
+   * one visibility modifier is set.
+   */
+  @Requires("modifier != null")
+  @Ensures("getModifiers().contains(modifier)")
+  public void addModifier(ElementModifier modifier) {
+    switch (modifier) {
+      case PRIVATE:
+      case PACKAGE_PRIVATE:
+      case PROTECTED:
+      case PUBLIC:
+        modifiers.remove(ElementModifier.PRIVATE);
+        modifiers.remove(ElementModifier.PACKAGE_PRIVATE);
+        modifiers.remove(ElementModifier.PROTECTED);
+        modifiers.remove(ElementModifier.PUBLIC);
+    }
+    modifiers.add(modifier);
+  }
+
+  /**
+   * Removes a modifier from this element. This method ensures that
+   * exactly one visibility modifier is set. It defaults to
+   * package-private if no other visibility is set.
+   */
+  @Requires("modifier != null")
+  @Ensures("!getModifiers().contains(modifier)")
+  public void removeModifier(ElementModifier modifier) {
+    modifiers.remove(modifier);
+    switch (modifier) {
+      case PRIVATE:
+      case PACKAGE_PRIVATE:
+      case PROTECTED:
+      case PUBLIC:
+        modifiers.add(ElementModifier.PACKAGE_PRIVATE);
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/model/TypeModel.java b/src/com/google/java/contract/core/model/TypeModel.java
new file mode 100644
index 0000000..f051bf5
--- /dev/null
+++ b/src/com/google/java/contract/core/model/TypeModel.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.Elements;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A model element representing a type.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "getName() != null",
+  "getSimpleName().equals(getName().getSimpleName())",
+  "getInterfaces() != null",
+  "!getInterfaces().contains(null)",
+  "getSuperArguments() != null",
+  "!getSuperArguments().contains(null)",
+  "getSuperclass() != null || superArguments.isEmpty()",
+  "getImportNames() != null",
+  "!getImportNames().contains(null)",
+  "getEnclosingElement() == null || importNames.isEmpty()"
+})
+public class TypeModel extends GenericElementModel {
+  /**
+   * The name of this type.
+   */
+  protected ClassName name;
+
+  /**
+   * The names of interfaces implemented by this type.
+   */
+  protected Set<ClassName> interfaces;
+
+  /**
+   * The name of the superclass of this type, if any.
+   */
+  protected ClassName superclass;
+
+  /**
+   * The types of the parameters to pass to the superclass constructor
+   * call.
+   */
+  protected List<TypeName> superArguments;
+
+  /**
+   * The values of import statements in effect in this source file.
+   */
+  protected Set<String> importNames;
+
+  /**
+   * Constructs a new TypeModel of the specified kind, with the
+   * specified name.
+   */
+  @Requires({
+    "kind != null",
+    "name != null",
+    "kind.isType()"
+  })
+  public TypeModel(ElementKind kind, ClassName name) {
+    super(kind, name.getSimpleName());
+    this.name = name;
+    interfaces = new HashSet<ClassName>();
+    superArguments = new ArrayList<TypeName>();
+    importNames = new HashSet<String>();
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  public TypeModel(TypeModel that) {
+    super(that);
+    name = that.name;
+    interfaces = new HashSet<ClassName>(that.interfaces);
+    superArguments = new ArrayList<TypeName>(that.superArguments);
+    importNames = new HashSet<String>(that.importNames);
+  }
+
+  @Override
+  public TypeModel clone() {
+    return new TypeModel(this);
+  }
+
+  public ClassName getName() {
+    return name;
+  }
+
+  @Requires({
+    "getEnclosingElement() == null",
+    "value != null"
+  })
+  @Ensures("getImportNames().contains(value)")
+  public void addImportName(String value) {
+    importNames.add(value);
+  }
+
+  @Requires({
+    "getEnclosingElement() == null",
+    "value != null"
+  })
+  @Ensures("!getImportNames().contains(value)")
+  public void removeImportName(String value) {
+    importNames.remove(value);
+  }
+
+  @Requires("getEnclosingElement() == null")
+  public Set<String> getImportNames() {
+    return Collections.unmodifiableSet(importNames);
+  }
+
+  public ClassName getSuperclass() {
+    return superclass;
+  }
+
+  public void setSuperclass(ClassName className) {
+    superclass = className;
+  }
+
+  @Ensures("result != null")
+  public List<? extends TypeName> getSuperArguments() {
+    return Collections.unmodifiableList(superArguments);
+  }
+
+  @Ensures("getSuperArguments().isEmpty()")
+  public void clearSuperArguments() {
+    superArguments.clear();
+  }
+
+  @Requires("typeName != null")
+  @Ensures({
+    "getSuperArguments().size() == old(getSuperArguments().size()) + 1",
+    "getSuperArguments().contains(typeName)"
+  })
+  public void addSuperArgument(TypeName typeName) {
+    superArguments.add(typeName);
+  }
+
+  public Set<? extends ClassName> getInterfaces() {
+    return Collections.unmodifiableSet(interfaces);
+  }
+
+  @Requires("className != null")
+  @Ensures("getInterfaces().contains(className)")
+  public void addInterface(ClassName className) {
+    interfaces.add(className);
+  }
+
+  @Requires("className != null")
+  @Ensures("!getInterfaces().contains(className)")
+  public void removeInterface(ClassName className) {
+    interfaces.remove(className);
+  }
+
+  @Ensures("result != null")
+  public List<? extends ContractAnnotationModel> getInvariants() {
+    return Elements.filter(enclosedElements, ContractAnnotationModel.class,
+                           ElementKind.INVARIANT);
+  }
+
+  @Requires({
+    "annotation != null",
+    "annotation.getKind() == ElementKind.INVARIANT"
+  })
+  @Ensures({
+    "getEnclosedElements().contains(annotation)",
+    "getInvariants().contains(annotation)"
+  })
+  public void addInvariant(ContractAnnotationModel annotation) {
+    addEnclosedElement(annotation);
+  }
+
+  @Requires({
+    "annotation != null",
+    "annotation.getKind() == ElementKind.INVARIANT"
+  })
+  @Ensures({
+    "!getEnclosedElements().contains(annotation)",
+    "!getInvariants().contains(annotation)"
+  })
+  public void removeInvariant(ContractAnnotationModel annotation) {
+    removeEnclosedElement(annotation);
+  }
+
+  @Ensures({
+    "result != null",
+    "!result.contains(null)"
+  })
+  public List<? extends QualifiedElementModel> getMembers() {
+    return Elements.filter(enclosedElements, QualifiedElementModel.class,
+                           ElementKind.CLASS,
+                           ElementKind.ENUM,
+                           ElementKind.INTERFACE,
+                           ElementKind.ANNOTATION_TYPE,
+                           ElementKind.FIELD,
+                           ElementKind.METHOD,
+                           ElementKind.CONSTRUCTOR,
+                           ElementKind.CONTRACT_METHOD,
+                           ElementKind.CONTRACT_MOCK);
+  }
+
+  @Requires({
+    "member != null",
+    "member.getKind().isMember()"
+  })
+  @Ensures({
+    "getEnclosedElements().contains(member)",
+    "getMembers().contains(member)"
+  })
+  public void addMember(QualifiedElementModel member) {
+    addEnclosedElement(member);
+  }
+
+  @Requires({
+    "member != null",
+    "member.getKind().isMember()"
+  })
+  @Ensures({
+    "!getEnclosedElements().contains(member)",
+    "!getMembers().contains(member)"
+  })
+  public void removeInvariant(QualifiedElementModel member) {
+    removeEnclosedElement(member);
+  }
+
+  @Override
+  public void accept(ElementVisitor visitor) {
+    visitor.visitType(this);
+  }
+
+  @Override
+  public EnumSet<ElementKind> getAllowedEnclosedKinds() {
+    EnumSet<ElementKind> allowed =
+        EnumSet.of(ElementKind.CLASS,
+                   ElementKind.ENUM,
+                   ElementKind.INTERFACE,
+                   ElementKind.ANNOTATION_TYPE,
+                   ElementKind.CONSTANT,
+                   ElementKind.FIELD,
+                   ElementKind.METHOD,
+                   ElementKind.CONSTRUCTOR,
+                   ElementKind.INVARIANT,
+                   ElementKind.CONTRACT_METHOD,
+                   ElementKind.CONTRACT_MOCK);
+    allowed.addAll(super.getAllowedEnclosedKinds());
+    return allowed;
+  }
+}
diff --git a/src/com/google/java/contract/core/model/TypeName.java b/src/com/google/java/contract/core/model/TypeName.java
new file mode 100644
index 0000000..927dc1a
--- /dev/null
+++ b/src/com/google/java/contract/core/model/TypeName.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+/**
+ * A type name, as it is used in source files.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("declaredName != null")
+public class TypeName {
+  protected String declaredName;
+
+  /**
+   * Constructs a new empty TypeName. This constructor is provided for
+   * convenience; {@link #declaredName} must be set on return from the
+   * child constructor.
+   */
+  protected TypeName() {
+  }
+
+  /**
+   * Constructs a new TypeName from its declared name.
+   */
+  @Requires("declaredName != null")
+  @Ensures("declaredName.equals(getDeclaredName())")
+  public TypeName(String declaredName) {
+    this.declaredName = declaredName;
+  }
+
+  @Ensures("result != null")
+  public String getDeclaredName() {
+    return declaredName;
+  }
+
+  /**
+   * Returns a string representation of this name usable in Java code.
+   */
+  @Override
+  public String toString() {
+    return declaredName;
+  }
+}
diff --git a/src/com/google/java/contract/core/model/VariableModel.java b/src/com/google/java/contract/core/model/VariableModel.java
new file mode 100644
index 0000000..24bed3d
--- /dev/null
+++ b/src/com/google/java/contract/core/model/VariableModel.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.model;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+/**
+ * A model element representing a variable (this classification
+ * includes parameters).
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("type != null")
+public class VariableModel extends QualifiedElementModel {
+  /**
+   * The type of this variable.
+   */
+  protected TypeName type;
+
+  /**
+   * Constructs a new VariableModel of the specified kind and type,
+   * with the specified name.
+   */
+  @Requires({
+    "kind != null",
+    "name != null",
+    "type != null",
+    "kind == ElementKind.CONSTANT " +
+        "|| kind == ElementKind.FIELD || kind == ElementKind.PARAMETER"
+  })
+  public VariableModel(ElementKind kind, String name, TypeName type) {
+    super(kind, name);
+    this.type = type;
+  }
+
+  /**
+   * Constructs a clone of {@code that}. The new object is identical
+   * to the original <em>except</em> it has no enclosing element.
+   */
+  @Requires("that != null")
+  @Ensures("getEnclosingElement() == null")
+  public VariableModel(VariableModel that) {
+    super(that);
+    type = that.type;
+  }
+
+  @Override
+  public VariableModel clone() {
+    return new VariableModel(this);
+  }
+
+  @Ensures("result != null")
+  public TypeName getType() {
+    return type;
+  }
+
+  @Requires("type != null")
+  public void setType(TypeName type) {
+    this.type = type;
+  }
+
+  @Override
+  public void accept(ElementVisitor visitor) {
+    visitor.visitVariable(this);
+  }
+}
diff --git a/src/com/google/java/contract/core/runtime/BlacklistManager.java b/src/com/google/java/contract/core/runtime/BlacklistManager.java
new file mode 100644
index 0000000..561986e
--- /dev/null
+++ b/src/com/google/java/contract/core/runtime/BlacklistManager.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.runtime;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.util.DebugUtils;
+import com.google.java.contract.core.util.PatternMap;
+
+/**
+ * A process-wide collection of blacklisted classes.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @see com.google.java.contract.ContractEnvironment#ignore(String)
+ */
+ at Invariant("blacklist != null")
+public class BlacklistManager {
+  protected static BlacklistManager instance = null;
+
+  protected PatternMap<Boolean> blacklist = new PatternMap<Boolean>();
+
+  protected BlacklistManager() {
+    blacklist = new PatternMap<Boolean>();
+    blacklist.put("java.*", true);
+    blacklist.put("javax.*", true);
+    blacklist.put("com.sun.*", true);
+    blacklist.put("sun.*", true);
+  }
+
+  public static BlacklistManager getInstance() {
+    if (instance == null) {
+      instance = new BlacklistManager();
+    }
+    return instance;
+  }
+
+  @Requires("pattern != null")
+  @Ensures("isIgnored(pattern)")
+  public synchronized void ignore(String pattern) {
+    DebugUtils.info("activation", pattern + " +blacklist");
+    blacklist.put(pattern, true);
+  }
+
+  @Requires("pattern != null")
+  @Ensures("!isIgnored(pattern)")
+  public synchronized void unignore(String pattern) {
+    DebugUtils.info("activation", pattern + " -blacklist");
+    blacklist.put(pattern, false);
+  }
+
+  @Requires("pattern != null")
+  public synchronized boolean isIgnored(String pattern) {
+    if (pattern.endsWith(".*") && blacklist.isOverriden(pattern)) {
+      return false;
+    }
+    Boolean rule = blacklist.get(pattern);
+    return rule != null && rule;
+  }
+}
diff --git a/src/com/google/java/contract/core/runtime/ContractContext.java b/src/com/google/java/contract/core/runtime/ContractContext.java
new file mode 100644
index 0000000..6e3d0cb
--- /dev/null
+++ b/src/com/google/java/contract/core/runtime/ContractContext.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.runtime;
+
+import java.util.IdentityHashMap;
+
+/**
+ * A helper to evaluate and enable method specifications. At runtime
+ * it is the interface between instrumented bytecode and Contracts for
+ * Java. Each thread has at most one context attached to it.
+ *
+ * <p>The ContractContext is responsible for:
+ *
+ * <ul>
+ * <li>Disabling contract checking inside of contracts.
+ * <li>Storage for failed predicate information.
+ * </ul>
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+public class ContractContext {
+  /**
+   * The default size of the {@link #entered} object map.
+   */
+  private static final int ENTERED_DEFAULT_SIZE = 100;
+
+  static ThreadLocal<ContractContext> context =
+      new ThreadLocal<ContractContext>() {
+    @Override
+    protected ContractContext initialValue() {
+      return new ContractContext();
+    }
+  };
+
+  protected boolean busy;
+  protected IdentityHashMap<Object, Void> entered;
+
+  protected ContractContext() {
+    entered = new IdentityHashMap<Object, Void>(ENTERED_DEFAULT_SIZE);
+  }
+
+  /**
+   * Marks the start of a contract evaluation block.
+   *
+   * @return {@code true} if contracts should be evaluated,
+   * {@code false} otherwise
+   */
+  public boolean tryEnterContract() {
+    if (busy) {
+      return false;
+    } else {
+      busy = true;
+      return true;
+    }
+  }
+
+  /**
+   * Marks the start of a contract evaluation block.
+   */
+  public void leaveContract() {
+    busy = false;
+  }
+
+  /**
+   * Queries whether invariants should be checked for the current
+   * method call. If it returns {@code true}, {@link #leave(Object)}
+   * must be called on method exit.
+   *
+   * @return {@code true} if invariants should be evaluated,
+   * {@code false} otherwise
+   */
+  public boolean tryEnter(Object obj) {
+    if (entered.containsKey(obj)) {
+      return false;
+    } else {
+      entered.put(obj, null);
+      return true;
+    }
+  }
+
+  /**
+   * Must be called if and only if {@link #tryEnter(Object)}
+   * previously returned {@code true} for this call frame.
+   */
+  public void leave(Object obj) {
+    entered.remove(obj);
+  }
+
+  /**
+   * Resets the busy state of this context.
+   */
+  public void clear() {
+    busy = false;
+  }
+}
diff --git a/src/com/google/java/contract/core/runtime/ContractRuntime.java b/src/com/google/java/contract/core/runtime/ContractRuntime.java
new file mode 100644
index 0000000..6e1ff1b
--- /dev/null
+++ b/src/com/google/java/contract/core/runtime/ContractRuntime.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 Google Inc.
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.runtime;
+
+import com.google.java.contract.ContractAssertionError;
+
+/**
+ * Utility methods for use in generated contract code.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class ContractRuntime {
+  /**
+   * Retrieves the contract context associated with the current
+   * thread.
+   */
+  public static ContractContext getContext() {
+    return ContractContext.context.get();
+  }
+
+  /**
+   * Resets the contract context and throws this assertion.
+   */
+  public static void raise(ContractAssertionError ex)
+      throws ContractAssertionError {
+    getContext().clear();
+    throw ex;
+  }
+
+  /**
+   * Magically casts the first argument to the type of the second
+   * argument.
+   *
+   * <p>This method is part of the old value type inference trick. It
+   * is called at run time to cast the old value variable (first
+   * argument) to the type of an unevaluated version of the old value
+   * expression (second argument). The "unevaluation" is achieved
+   * through a constant conditional (for example,
+   * {@code true ? null : oldExpression}).
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> T magicCast(Object obj, T dummy) {
+    return (T) obj;
+  }
+}
diff --git a/src/com/google/java/contract/core/runtime/RuntimeContractEnvironment.java b/src/com/google/java/contract/core/runtime/RuntimeContractEnvironment.java
new file mode 100644
index 0000000..6353551
--- /dev/null
+++ b/src/com/google/java/contract/core/runtime/RuntimeContractEnvironment.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.runtime;
+
+import com.google.java.contract.ContractEnvironment;
+
+/**
+ * A contract environment running under the Cofoja Java agent.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class RuntimeContractEnvironment implements ContractEnvironment {
+  protected BlacklistManager blacklistManager;
+
+  public RuntimeContractEnvironment() {
+    blacklistManager = BlacklistManager.getInstance();
+  }
+
+  @Override
+  public void enablePreconditions(String pattern) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void disablePreconditions(String pattern) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void enablePostconditions(String pattern) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void disablePostconditions(String pattern) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void enableInvariants(String pattern) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void disableInvariants(String pattern) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public boolean hasPreconditionsEnabled(Class<?> clazz) {
+    return false;
+  }
+
+  @Override
+  public boolean hasPreconditionsEnabled(String pattern) {
+    return false;
+  }
+
+  @Override
+  public boolean hasPostconditionsEnabled(Class<?> clazz) {
+    return false;
+  }
+
+  @Override
+  public boolean hasPostconditionsEnabled(String pattern) {
+    return false;
+  }
+
+  @Override
+  public boolean hasInvariantsEnabled(Class<?> clazz) {
+    return false;
+  }
+
+  @Override
+  public boolean hasInvariantsEnabled(String pattern) {
+    return false;
+  }
+
+  @Override
+  public void ignore(String pattern) {
+    blacklistManager.ignore(pattern);
+  }
+
+  @Override
+  public void unignore(String pattern) {
+    blacklistManager.unignore(pattern);
+  }
+
+  @Override
+  public boolean isIgnored(String pattern) {
+    return blacklistManager.isIgnored(pattern);
+  }
+}
diff --git a/src/com/google/java/contract/core/util/BalancedTokenizer.java b/src/com/google/java/contract/core/util/BalancedTokenizer.java
new file mode 100644
index 0000000..b93b771
--- /dev/null
+++ b/src/com/google/java/contract/core/util/BalancedTokenizer.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+
+/**
+ * A tokenizer that processes Java balanced expressions. In addition
+ * to the work of a {@link LineNumberingTokenizer}, a
+ * BalancedTokenizer also keeps track of punctuation balancing. It
+ * knows about parentheses, square brackets, and braces.
+ *
+ * <p>It doesn't check uses of angle brackets, because of the added
+ * complexity. This is usually not an issue, though, as, in Java, type
+ * parameters have a very limited syntax.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "stack != null",
+  "!stack.contains(null)"
+})
+public class BalancedTokenizer extends LineNumberingTokenizer {
+  /**
+   * Balanced punctuation stack. Opening punctuationm symbols are
+   * stored in this stack.
+   */
+  protected Deque<Character> stack;
+
+  /**
+   * Constructs a new BalancedTokenizer reading characters from
+   * {@code reader}.
+   */
+  @Requires("reader != null")
+  public BalancedTokenizer(Reader reader) {
+    super(reader);
+    stack = new ArrayDeque<Character>();
+  }
+
+  @Ensures({
+    "result != null",
+    "result.size() == getCurrentLevel()"
+  })
+  public Collection<Character> getStack() {
+    return Collections.unmodifiableCollection(stack);
+  }
+
+  @Ensures({
+    "result >= 0",
+    "result == getStack().size()"
+  })
+  public int getCurrentLevel() {
+    return stack.size();
+  }
+
+  @Requires("\"()[]{}\".indexOf(c) != -1")
+  protected char getMatchingDelimiter(char c) {
+    switch (c) {
+      case '(':
+        return ')';
+      case '[':
+        return ']';
+      case '{':
+        return '}';
+      case ')':
+        return '(';
+      case ']':
+        return '[';
+      case '}':
+        return '{';
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  protected boolean lex() throws IOException {
+    if (!super.lex()) {
+      if (!stack.isEmpty()) {
+        char d = getMatchingDelimiter(stack.pop());
+        errorMessage = "'" + d + "' expected";
+        hasErrors_ = true;
+        return false;
+      }
+      return false;
+    }
+    if (nextToken.kind == TokenKind.SYMBOL) {
+      char c = nextToken.text.charAt(0);
+      switch (c) {
+        case '(':
+        case '[':
+        case '{':
+          stack.push(c);
+          break;
+        case ')':
+        case ']':
+        case '}':
+          String error = null;
+          if (stack.isEmpty()) {
+            error = "unexpected '" + c + "'";
+          } else {
+            char d = getMatchingDelimiter(stack.pop());
+            if (d != c) {
+              error = "'" + d + "' expected";
+            }
+          }
+          if (error != null) {
+            unreadChar(c);
+            nextToken = null;
+
+            errorMessage = error;
+            hasErrors_ = true;
+            return false;
+          }
+          break;
+        default:
+          break;
+      }
+    }
+    return true;
+  }
+}
diff --git a/src/com/google/java/contract/core/util/DebugUtils.java b/src/com/google/java/contract/core/util/DebugUtils.java
new file mode 100644
index 0000000..1972d86
--- /dev/null
+++ b/src/com/google/java/contract/core/util/DebugUtils.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import javax.tools.JavaFileObject;
+
+/**
+ * Utility methods for debugging.
+ */
+public class DebugUtils {
+  private static String dumpDirectory = "contracts_for_java.out";
+
+  private static Map<String, Boolean> loggingEnabled =
+      new HashMap<String, Boolean>();
+
+  @Ensures("result != null")
+  public static String getDumpDirectory() {
+    return dumpDirectory;
+  }
+
+  @Requires("dir != null")
+  @Ensures("getDumpDirectory().equals(dir)")
+  public static void setDumpDirectory(String dir) {
+    dumpDirectory = dir;
+  }
+
+  /**
+   * Dumps the specified Java file (source, class, etc.) to the dump
+   * directory (by default, "contracts_for_java.out" in the current
+   * directory).
+   *
+   * @param name the qualified class name of the file to dump
+   * @param data the file content
+   * @param kind the kind of file to dump
+   */
+  @Requires({
+    "name != null",
+    "data != null",
+    "kind != null"
+  })
+  public static void dump(String name, byte[] data, JavaFileObject.Kind kind) {
+    File f = new File(dumpDirectory + "/" + name + kind.extension);
+    info("dump", "dumping file " + f);
+    f.getParentFile().mkdirs();
+    try {
+      OutputStream out = new FileOutputStream(f);
+      out.write(data);
+      out.flush();
+      out.close();
+    } catch (IOException e) {
+      warn("dump", "while dumping " + f + ": " + e.getMessage());
+    }
+  }
+
+  @Requires("facility != null")
+  public static boolean isLoggingEnabled(String facility) {
+    Boolean enabled = loggingEnabled.get(facility);
+    if (enabled == null) {
+      enabled = Boolean.valueOf(
+          System.getProperty("com.google.java.contract.log." + facility, "false"));
+      loggingEnabled.put(facility, enabled);
+    }
+    return enabled;
+  }
+
+  /**
+   * Outputs an informative message regarding contract
+   * activation. Does not bear any contracts itself so as not to
+   * pollute the output.
+   */
+  public static void contractInfo(String message) {
+    if (isLoggingEnabled("contract")) {
+      System.err.println("[com.google.java.contract:contract "
+                         + message + "]");
+    }
+  }
+
+  @Requires({
+    "facility != null",
+    "message != null"
+  })
+  public static void info(String facility, String message) {
+    if (isLoggingEnabled(facility)) {
+      System.err.println("[com.google.java.contract:" + facility + " "
+                         + message + "]");
+    }
+  }
+
+  @Requires({
+    "facility != null",
+    "message != null"
+  })
+  public static void warn(String facility, String message) {
+    System.err.println("[com.google.java.contract:" + facility + " "
+                       + message + "]");
+  }
+
+  @Requires({
+    "facility != null",
+    "message != null"
+  })
+  public static void err(String facility, String message, Throwable cause) {
+    System.err.println("[com.google.java.contract:" + facility + " FATAL ERROR "
+                       + message
+                       + (cause != null ? " (stack trace follows)" : "")
+                       + "]");
+    if (cause != null) {
+      cause.printStackTrace();
+    } else {
+      new Exception().printStackTrace();
+    }
+    System.exit(1);
+  }
+}
diff --git a/src/com/google/java/contract/core/util/ElementScanner.java b/src/com/google/java/contract/core/util/ElementScanner.java
new file mode 100644
index 0000000..51eb7f4
--- /dev/null
+++ b/src/com/google/java/contract/core/util/ElementScanner.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ContractMethodModel;
+import com.google.java.contract.core.model.ElementModel;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.VariableModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A scanner that recursively descends into an {@link Element}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+public abstract class ElementScanner extends EmptyElementVisitor {
+  @Requires({
+    "elements != null",
+    "!elements.contains(null)"
+  })
+  public void scan(List<? extends ElementModel> elements) {
+    ArrayList<? extends ElementModel> tmp =
+        new ArrayList<ElementModel>(elements);
+    for (ElementModel element : tmp) {
+      element.accept(this);
+    }
+  }
+
+  @Override
+  public void visitType(TypeModel type) {
+    scan(type.getEnclosedElements());
+  }
+
+  @Override
+  public void visitVariable(VariableModel variable) {
+    scan(variable.getEnclosedElements());
+  }
+
+  @Override
+  public void visitMethod(MethodModel method) {
+    scan(method.getEnclosedElements());
+  }
+
+  @Override
+  public void visitContractMethod(ContractMethodModel contract) {
+    scan(contract.getEnclosedElements());
+  }
+
+  @Override
+  public void visitContractAnnotation(ContractAnnotationModel annotation) {
+    scan(annotation.getEnclosedElements());
+  }
+}
diff --git a/src/com/google/java/contract/core/util/Elements.java b/src/com/google/java/contract/core/util/Elements.java
new file mode 100644
index 0000000..9bdc99a
--- /dev/null
+++ b/src/com/google/java/contract/core/util/Elements.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ElementKind;
+import com.google.java.contract.core.model.ElementModel;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.VariableModel;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Utility methods to ease working with {@link ElementModel} objects.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @author johannes.rieken at gmail.com (Johannes Rieken)
+ */
+public class Elements {
+  /**
+   * Adds a copy of the {@code parameters} to {@code method}.
+   */
+  @Requires({
+    "method != null",
+    "parameters != null",
+    "!parameters.contains(null)"
+  })
+  public static void copyParameters(MethodModel method,
+                                    List<? extends VariableModel> parameters) {
+    ArrayList<VariableModel> list = new ArrayList<VariableModel>(parameters);
+    for (VariableModel param : list) {
+      method.addParameter(new VariableModel(param));
+    }
+  }
+
+  /**
+   * Returns the sublist of all elements of the specified kinds.
+   */
+  @Requires({
+    "elements != null",
+    "!elements.contains(null)",
+    "clazz != null",
+    "kinds != null"
+  })
+  @SuppressWarnings("unchecked")
+  public static <T extends ElementModel> List<? extends T> filter(
+      List<? extends ElementModel> elements, Class<T> clazz,
+      ElementKind... kinds) {
+    ArrayList<T> result = new ArrayList<T>();
+    List<ElementKind> list = Arrays.asList(kinds);
+    for (ElementModel element : elements) {
+      if (list.contains(element.getKind())
+          && clazz.isAssignableFrom(element.getClass())) {
+        result.add((T) element);
+      }
+    }
+    return Collections.unmodifiableList(result);
+  }
+
+  /**
+   * Returns the closest enclosing element of the specified kind.
+   */
+  @Requires({
+    "element != null",
+    "clazz != null",
+    "kinds != null"
+  })
+  @SuppressWarnings("unchecked")
+  public static <T extends ElementModel> T findEnclosingElement(
+      ElementModel element, Class<T> clazz, ElementKind... kinds) {
+    List<ElementKind> list = Arrays.asList(kinds);
+    for (;;) {
+      element = element.getEnclosingElement();
+      if (element == null) {
+        return null;
+      }
+      if (list.contains(element.getKind())
+          && clazz.isAssignableFrom(element.getClass())) {
+        return (T) element;
+      }
+    }
+  }
+
+  /**
+   * Returns the closest enclosing type of the specified element.
+   */
+  @Requires("element != null")
+  public static TypeModel getTypeOf(ElementModel element) {
+    return findEnclosingElement(element, TypeModel.class,
+        ElementKind.CLASS, ElementKind.ENUM, ElementKind.INTERFACE);
+  }
+
+  /**
+   * Returns a Contracts for Java private URI for the specified class name
+   * and kind.
+   */
+  @Requires({
+    "name != null",
+    "!name.isEmpty()",
+    "kind != null"
+  })
+  public static URI getUriForClass(String name, Kind kind) {
+    try {
+      return new URI("com.google.java.contract://com.google.java.contract/" + name + kind.extension);
+    } catch (URISyntaxException e) {
+      throw new IllegalArgumentException();
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/util/EmptyElementVisitor.java b/src/com/google/java/contract/core/util/EmptyElementVisitor.java
new file mode 100644
index 0000000..e5bf11f
--- /dev/null
+++ b/src/com/google/java/contract/core/util/EmptyElementVisitor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.core.model.ContractAnnotationModel;
+import com.google.java.contract.core.model.ContractMethodModel;
+import com.google.java.contract.core.model.ElementVisitor;
+import com.google.java.contract.core.model.MethodModel;
+import com.google.java.contract.core.model.TypeModel;
+import com.google.java.contract.core.model.VariableModel;
+
+/**
+ * An element visitor that does nothing.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public abstract class EmptyElementVisitor implements ElementVisitor {
+  @Override
+  public void visitType(TypeModel type) {
+  }
+
+  @Override
+  public void visitVariable(VariableModel variable) {
+  }
+
+  @Override
+  public void visitMethod(MethodModel method) {
+  }
+
+  @Override
+  public void visitContractMethod(ContractMethodModel contract) {
+  }
+
+  @Override
+  public void visitContractAnnotation(ContractAnnotationModel annotation) {
+  }
+}
diff --git a/src/com/google/java/contract/core/util/JavaTokenizer.java b/src/com/google/java/contract/core/util/JavaTokenizer.java
new file mode 100644
index 0000000..29b8d46
--- /dev/null
+++ b/src/com/google/java/contract/core/util/JavaTokenizer.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A tokenizer that processes Java expressions. It knows about words,
+ * quoted strings, comments, and white space. Symbols are <em>not</em>
+ * aggregated into operators.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("reader != null")
+public class JavaTokenizer implements Iterator<JavaTokenizer.Token> {
+  /**
+   * The kind of a token.
+   */
+  public static enum TokenKind {
+    /**
+     * An identifier or keyword.
+     */
+    WORD,
+
+    /**
+     * A quoted literal.
+     */
+    QUOTE,
+
+    /**
+     * A punctuation symbol.
+     */
+    SYMBOL,
+
+    /**
+     * A comment.
+     */
+    COMMENT,
+
+    /**
+     * A sequence of whitespace.
+     */
+    SPACE;
+  }
+
+  /**
+   * A token returned by an instance of JavaTokenizer.
+   */
+  public class Token {
+    public final TokenKind kind;
+    public final String text;
+    public final int offset;
+
+    protected Token(TokenKind kind, String text, int offset) {
+      this.kind = kind;
+      this.text = text;
+      this.offset = offset;
+    }
+  }
+
+  /**
+   * The source of characters to tokenize.
+   */
+  protected PushbackReader reader;
+
+  /**
+   * The next token returned by this tokenizer, or {@code null} if
+   * none (end of file or not read yet).
+   */
+  protected Token nextToken;
+
+  /**
+   * {@code true} if an error was found during tokenization.
+   */
+  protected boolean hasErrors_;
+
+  /**
+   * The error message, if an error has occurred. Can be {@code null}.
+   */
+  protected String errorMessage;
+
+  /**
+   * The number of characters read by this tokenizer.
+   */
+  protected int currentOffset;
+
+  /**
+   * Constructs a new JavaTokenizer reading characters from
+   * {@code reader}.
+   */
+  @Requires("reader != null")
+  public JavaTokenizer(Reader reader) {
+    this.reader = new PushbackReader(reader);
+    nextToken = null;
+    hasErrors_ = false;
+    currentOffset = 0;
+  }
+
+  /**
+   * Reads a character from {@code reader}. In this implementation,
+   * all read accesses to the reader pass through this method.
+   *
+   * @param allowEOF if {@code false}, throws IOException if EOF is
+   * reached
+   */
+  @Ensures({
+    "!allowEOF ? result >= 0 : result >= -1"
+  })
+  protected int readChar(boolean allowEOF) throws IOException {
+    int c = reader.read();
+    if (c != -1) {
+      ++currentOffset;
+    } else {
+      if (!allowEOF) {
+        throw new IOException();
+      }
+    }
+    return c;
+  }
+
+  /**
+   * Pushes back a character into {@code reader}. In this
+   * implementation, all unread accesses to the reader pass through
+   * this method.
+   */
+  protected void unreadChar(int c) throws IOException {
+    if (c == -1) {
+      return;
+    }
+    --currentOffset;
+    reader.unread(c);
+  }
+
+  /**
+   * Reads the next token into {@code nextToken}.
+   *
+   * @return {@code true} if a new token was successfully read
+   */
+  @Requires("nextToken == null")
+  @Ensures("result == (nextToken != null)")
+  protected boolean lex() throws IOException {
+    int startOffset = currentOffset;
+    StringBuilder buffer = new StringBuilder();
+    int c = readChar(true);
+    if (c == -1) {
+      return false;
+    }
+    buffer.append((char) c);
+    switch (c) {
+      case '/':
+        /* Comments. */
+        c = readChar(true);
+        switch (c) {
+          case '/':
+            buffer.append((char) c);
+            do {
+              c = readChar(false);
+              buffer.append((char) c);
+            } while (c != '\n');
+            nextToken = new Token(TokenKind.COMMENT, buffer.toString(),
+                                  startOffset);
+            break;
+          case '*':
+            buffer.append((char) c);
+            for (;;) {
+              c = readChar(false);
+              buffer.append((char) c);
+              if (c == '*') {
+                c = readChar(false);
+                buffer.append((char) c);
+                if (c == '/') {
+                  break;
+                }
+              }
+            }
+            nextToken = new Token(TokenKind.COMMENT, buffer.toString(),
+                                  startOffset);
+            break;
+          default:
+            unreadChar(c);
+            nextToken = new Token(TokenKind.SYMBOL, buffer.toString(),
+                                  startOffset);
+        }
+        break;
+
+      case '\'':
+      case '"':
+        /* Quoted strings. */
+        int delim = c;
+        for (;;) {
+          c = readChar(false);
+          buffer.append((char) c);
+          if (c == delim) {
+            break;
+          }
+          if (c == '\\') {
+            buffer.append((char) readChar(false));
+          }
+        }
+        nextToken = new Token(TokenKind.QUOTE, buffer.toString(), startOffset);
+        break;
+
+      default:
+        if (Character.isJavaIdentifierStart(c)) {
+          /* Identifiers. */
+          while ((c = readChar(true)) != -1
+                 && Character.isJavaIdentifierPart(c)) {
+            buffer.append((char) c);
+          }
+          unreadChar(c);
+          nextToken = new Token(TokenKind.WORD, buffer.toString(), startOffset);
+        } else if (Character.isWhitespace(c)) {
+          /* White space. */
+          while ((c = readChar(true)) != -1 && Character.isWhitespace(c)) {
+            buffer.append((char) c);
+          }
+          unreadChar(c);
+          nextToken = new Token(TokenKind.SPACE, buffer.toString(),
+                                startOffset);
+        } else {
+          /* Symbol. */
+          nextToken = new Token(TokenKind.SYMBOL, buffer.toString(),
+                                startOffset);
+        }
+    }
+    return true;
+  }
+
+  /**
+   * Returns the next token without consuming it.
+   */
+  public Token getNextToken() {
+    if (nextToken == null) {
+      try {
+        if (!lex()) {
+          throw new NoSuchElementException();
+        }
+      } catch (IOException e) {
+        errorMessage = e.getMessage();
+        hasErrors_ = true;
+        throw new NoSuchElementException();
+      }
+    }
+    return nextToken;
+  }
+
+  public int getCurrentOffset() {
+    return currentOffset;
+  }
+
+  /**
+   * Returns {@code true} if an error has been found.
+   */
+  public boolean hasErrors() {
+    return hasErrors_;
+  }
+
+  @Requires("hasErrors()")
+  public String getErrorMessage() {
+    return errorMessage;
+  }
+
+  @Override
+  public boolean hasNext() {
+    if (nextToken != null) {
+      return true;
+    } else {
+      try {
+        return lex();
+      } catch (IOException e) {
+        errorMessage = e.getMessage();
+        hasErrors_ = true;
+        return false;
+      }
+    }
+  }
+
+  @Override
+  public Token next() {
+    Token token = getNextToken();
+    nextToken = null;
+    return token;
+  }
+
+  @Override
+  public void remove() {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git a/src/com/google/java/contract/core/util/JavaUtils.java b/src/com/google/java/contract/core/util/JavaUtils.java
new file mode 100644
index 0000000..155ba0d
--- /dev/null
+++ b/src/com/google/java/contract/core/util/JavaUtils.java
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Map;
+import java.util.regex.Pattern;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Utility methods related to the Java language.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at AllowUnusedImport(ClassName.class)
+public class JavaUtils {
+  /**
+   * A parse error; thrown by the parsing functions whenever they read
+   * an unexpected token in Java code.
+   */
+  public static class ParseException extends Exception {
+    public ParseException(String msg) {
+      super(msg);
+    }
+
+    public ParseException(Throwable cause) {
+      super(cause);
+    }
+
+    public ParseException(String msg, Throwable cause) {
+      super(msg, cause);
+    }
+  }
+
+  /**
+   * File name extension of contract class files.
+   */
+  public static final String CONTRACTS_EXTENSION = ".contracts";
+
+  /**
+   * File name extension of contracted class files.
+   */
+  public static final String CONTRACTED_EXTENSION = ".class.contracted";
+
+  /**
+   * File name extension of source dependency information files.
+   */
+  public static final String SOURCE_DEPENDENCY_EXTENSION = ".java.d";
+
+  /**
+   * A comment string that marks the beginning of generated code.
+   */
+  public static final String BEGIN_GENERATED_CODE = "/*[*/";
+
+  /**
+   * A comment string that marks the end of generated code.
+   */
+  public static final String END_GENERATED_CODE = "/*]*/";
+
+  /**
+   * A comment delimiter string that marks the beginning of a location
+   * comment, used to track code positions in errors.
+   */
+  public static final String BEGIN_LOCATION_COMMENT = "/*[";
+
+  /**
+   * A comment delimiter string that marks the end of a location
+   * comment, used to track code positions in errors.
+   */
+  public static final String END_LOCATION_COMMENT = "]*/";
+
+  /**
+   * The name of the <em>user-visible</em> result variable.
+   */
+  public static final String RESULT_VARIABLE =
+      "result";
+
+  /**
+   * The name of the <em>user-visible</em> signal variable.
+   */
+  public static final String SIGNAL_VARIABLE =
+      "signal";
+
+  /**
+   * The suffix appended to helper class names.
+   */
+  public static final String HELPER_CLASS_SUFFIX =
+      "$com$google$java$contract$H";
+
+  /**
+   * The prefix added to synthetic member names.
+   */
+  public static final String SYNTHETIC_MEMBER_PREFIX =
+      "com$google$java$contract$S";
+
+  /**
+   * The prefix of all old variable names.
+   */
+  public static final String OLD_VARIABLE_PREFIX =
+      "com$google$java$contract$local$old";
+
+  /**
+   * The prefix of all temporary variables that are assigned the value
+   * of assertion expressions. Their purpose is to syntactically
+   * isolate the user expression in order to get better error
+   * messages, and provide markers for debug line numbering.
+   */
+  public static final String SUCCESS_VARIABLE_PREFIX =
+      "com$google$java$contract$local$success";
+
+  /**
+   * The prefix of all temporary variables for exceptions thrown during
+   * assertion expression evaluation.
+   */
+  public static final String EXCEPTION_VARIABLE_PREFIX =
+      "com$google$java$contract$local$exception";
+
+  /**
+   * The name of a temporary variable that keeps track of failed
+   * contravariant conditions.
+   */
+  public static final String ERROR_VARIABLE =
+      "com$google$java$contract$local$error";
+
+  /**
+   * The name of the parameter holding the object to evaluate the
+   * predicates against, in interface helper contract methods.
+   */
+  public static final String THAT_VARIABLE =
+      "com$google$java$contract$local$that";
+
+  /**
+   * Returns {@code true} if {@code obj} can be cast to class
+   * {@code className}, at run time, using reflection.
+   */
+  @Requires({
+    "obj != null",
+    "className != null"
+  })
+  public static boolean objectIsCastableTo(Object obj, String className) {
+    try {
+      Class<?> clazz = Class.forName(className);
+      return clazz.isAssignableFrom(obj.getClass());
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  @Requires("className != null")
+  public static boolean classExists(String className) {
+    try {
+      Class.forName(className);
+      return true;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  /**
+   * Quotes {@code str} so as to be readily inserted into a Java
+   * "multi-line" comment.
+   */
+  @Requires("str != null")
+  @Ensures("result != null")
+  public static String quoteComment(String str) {
+    return str.replace("/*", "/\\*").replace("*/", "*\\/");
+  }
+
+  /**
+   * Deletes Java comments from {@code code} and returns the resulting
+   * string.
+   */
+  @Requires("code != null")
+  @Ensures("result != null")
+  public static String deleteComments(String code) {
+    StringBuilder buffer = new StringBuilder();
+    JavaTokenizer tokenizer = new JavaTokenizer(new StringReader(code));
+    while (tokenizer.hasNext()) {
+      JavaTokenizer.Token token = tokenizer.next();
+      if (token.kind != JavaTokenizer.TokenKind.COMMENT) {
+        buffer.append(token.text);
+      }
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Deletes generated Java code from {@code code} and returns the
+   * resulting string. Generated code is delimited by matching
+   * {@link #BEGIN_DEBUG_COMMENT} and {@link #END_GENERATED_CODE}
+   * comments.
+   */
+  @Requires("code != null")
+  @Ensures({
+    "result != null",
+    "code.length() == result.length() + generatedCodeLength(code)"
+  })
+  public static String deleteGeneratedCode(String code) {
+    StringBuilder buffer = new StringBuilder();
+    JavaTokenizer tokenizer = new JavaTokenizer(new StringReader(code));
+    boolean ignore = false;
+    while (tokenizer.hasNext()) {
+      JavaTokenizer.Token token = tokenizer.next();
+      if (!ignore) {
+        if (token.kind == JavaTokenizer.TokenKind.COMMENT
+            && token.text.equals(BEGIN_GENERATED_CODE)) {
+          ignore = true;
+        } else {
+          buffer.append(token.text);
+        }
+      } else {
+        if (token.kind == JavaTokenizer.TokenKind.COMMENT
+            && token.text.equals(END_GENERATED_CODE)) {
+          ignore = false;
+        }
+      }
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Returns the number of characters used in {@code code} for
+   * generated code.
+   *
+   * @see #deleteGeneratedCode(String)
+   */
+  @Requires("code != null")
+  @Ensures("result == code.length() - deleteGeneratedCode(code).length()")
+  public static int generatedCodeLength(String code) {
+    int length = 0;
+    JavaTokenizer tokenizer = new JavaTokenizer(new StringReader(code));
+    boolean ignore = false;
+    while (tokenizer.hasNext()) {
+      JavaTokenizer.Token token = tokenizer.next();
+      if (!ignore) {
+        if (token.kind == JavaTokenizer.TokenKind.COMMENT
+            && token.text.equals(BEGIN_GENERATED_CODE)) {
+          ignore = true;
+          length += token.text.length();
+        }
+      } else {
+        if (token.kind == JavaTokenizer.TokenKind.COMMENT
+            && token.text.equals(END_GENERATED_CODE)) {
+          ignore = false;
+        }
+        length += token.text.length();
+      }
+    }
+    return length;
+  }
+
+  /**
+   * Returns {@code code} with all unqualified identifiers remapped
+   * according to {@code map}.
+   */
+  @Requires({
+    "code != null",
+    "map != null"
+  })
+  @Ensures("result != null")
+  public static String renameLocalVariables(String code,
+                                            Map<String, String> map) {
+    StringBuilder buffer = new StringBuilder();
+    JavaTokenizer tokenizer = new JavaTokenizer(new StringReader(code));
+    boolean qualified = false;
+    while (tokenizer.hasNext()) {
+      JavaTokenizer.Token token = tokenizer.next();
+      if (!qualified && token.kind == JavaTokenizer.TokenKind.WORD) {
+        String replacement = map.get(token.text);
+        if (replacement != null) {
+          buffer.append(replacement);
+        } else {
+          buffer.append(token.text);
+        }
+      } else {
+        buffer.append(token.text);
+      }
+      qualified = token.text.equals(".");
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Returns {@code true} if the next token in {@code tokenizer},
+   * disregarding whitespace, matches {@code text}.
+   */
+  @Requires({
+    "tokenizer != null",
+    "text != null"
+  })
+  public static boolean lookingAt(PushbackTokenizer tokenizer, String text) {
+    JavaTokenizer.Token token1 = tokenizer.peek(0);
+    JavaTokenizer.Token token2 = tokenizer.peek(1);
+    if (token1 == null) {
+      return false;
+    }
+    if (!token1.text.equals(text)) {
+      if (token1.kind != JavaTokenizer.TokenKind.SPACE) {
+        return false;
+      }
+      if (token2 == null) {
+        return false;
+      }
+      if (!token2.text.equals(text)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Advances {@code tokenizer} past the next occurrence of
+   * {@code text} (which must match a full token).
+   */
+  @Requires({
+    "tokenizer != null",
+    "text != null"
+  })
+  public static void skipPast(JavaTokenizer tokenizer, String text) {
+    while (tokenizer.hasNext() && !tokenizer.next().text.equals(text)) {
+    }
+  }
+
+  /**
+   * Parses a Java fully-qualified identifier and positions
+   * {@code tokenizer} on the next token.
+   *
+   * @param tokenizer the tokenizer to read from
+   * @param acceptStar {@code true} if the name can end in {@code .*}
+   * @return the parsed identifier
+   * @throws ParseException if the tokenizer is not at the start of an
+   * identifier
+   */
+  @Requires("tokenizer != null")
+  @Ensures(
+    "!acceptStar ? ClassName.isQualifiedName(result)" +
+        ": ClassName.isQualifiedName(result)" +
+        "|| ClassName.isQualifiedName(result.substring(0, result.length() - 2))"
+  )
+  public static String parseQualifiedName(JavaTokenizer tokenizer,
+                                          boolean acceptStar)
+      throws ParseException {
+    StringBuilder buffer = new StringBuilder();
+    boolean expectWord = true;
+   loop:
+    while (tokenizer.hasNext()) {
+      JavaTokenizer.Token token = tokenizer.getNextToken();
+      switch (token.kind) {
+        case WORD:
+          if (expectWord) {
+            buffer.append(token.text);
+            expectWord = false;
+          } else {
+            break loop;
+          }
+          break;
+        case SYMBOL:
+          switch (token.text.charAt(0)) {
+            case '.':
+              if (!expectWord) {
+                buffer.append(".");
+                expectWord = true;
+                break;
+              } else {
+                break loop;
+              }
+            case '*':
+              if (acceptStar && expectWord) {
+                buffer.append("*");
+                tokenizer.next();
+              }
+              break loop;
+            default:
+              break loop;
+          }
+          break;
+        case SPACE:
+          break;
+        default:
+          break loop;
+      }
+      tokenizer.next();
+    }
+    if (buffer.length() == 0) {
+      throw new ParseException("next token is not part of an identifier");
+    }
+    return buffer.toString();
+  }
+
+  public static String parseQualifiedName(JavaTokenizer tokenizer)
+      throws ParseException {
+    return parseQualifiedName(tokenizer, false);
+  }
+
+  /**
+   * Returns a {@link URLClassLoader} that searches {@code path} and
+   * delegates to {@code parent}.
+   */
+  @Requires("path != null")
+  public static URLClassLoader getLoaderForPath(String path,
+                                                ClassLoader parent) {
+    String[] parts = path.split(Pattern.quote(File.pathSeparator));
+    URL[] urls = new URL[parts.length];
+    for (int i = 0; i < parts.length; ++i) {
+      try {
+        urls[i] = new File(parts[i]).toURI().toURL();
+      } catch (MalformedURLException e) {
+        /* Ignore erroneous paths. */
+      }
+    }
+    if (parent == null) {
+      return new URLClassLoader(urls);
+    } else {
+      return new URLClassLoader(urls, parent);
+    }
+  }
+
+  @Requires("path != null")
+  public static URLClassLoader getLoaderForPath(String path) {
+    return getLoaderForPath(path, null);
+  }
+
+  /**
+   * Reads the class file of the specified class, as a stream. The
+   * class file is searched in the following places, in order:
+   *
+   * <ol>
+   * <li>The resources of the current class loader, if any.
+   * <li>The resources of the system class loader.
+   * </ol>
+   *
+   * @param loader the class loader used to load resources
+   * @param className the class name, in binary format
+   * @return the content of the contract class file, as a stream, or
+   * {@code null} if none was found
+   */
+  @Requires("ClassName.isBinaryName(className)")
+  public static InputStream getClassInputStream(ClassLoader loader,
+                                                String className) {
+    String fileName = className + Kind.CLASS.extension;
+    URL url;
+
+    if (loader != null) {
+      url = loader.getResource(fileName);
+      if (url == null) {
+        return null;
+      } else {
+        DebugUtils.info("loader", "found " + url);
+        return loader.getResourceAsStream(fileName);
+      }
+    } else {
+      url = ClassLoader.getSystemResource(fileName);
+      if (url == null) {
+        return null;
+      } else {
+        DebugUtils.info("loader", "found " + url);
+        return ClassLoader.getSystemResourceAsStream(fileName);
+      }
+    }
+  }
+
+  /**
+   * Reads the contract class file of the specified class, as a
+   * stream. The contract class file is searched in the following
+   * places, in order:
+   *
+   * <ol>
+   * <li>The resources of the current class loader, if any.
+   * <li>The resources of the system class loader.
+   * </ol>
+   *
+   * @param loader the class loader used to load resources
+   * @param className the class name, in binary format
+   * @return the content of the contract class file, as a stream, or
+   * {@code null} if none was found
+   */
+  @Requires("ClassName.isBinaryName(className)")
+  public static InputStream getContractClassInputStream(ClassLoader loader,
+                                                        String className,
+                                                        boolean loadHelper) {
+    String fileName = className + CONTRACTS_EXTENSION;
+    String helperFileName = className + HELPER_CLASS_SUFFIX
+        + Kind.CLASS.extension;
+
+    URL url;
+
+    if (loader != null) {
+      url = loader.getResource(helperFileName);
+      if (url != null && loadHelper) {
+        DebugUtils.info("loader", "found " + url);
+        return loader.getResourceAsStream(helperFileName);
+      }
+
+      url = loader.getResource(fileName);
+      if (url != null) {
+        DebugUtils.info("loader", "found " + url);
+        return loader.getResourceAsStream(fileName);
+      }
+
+      return null;
+    } else {
+      url = ClassLoader.getSystemResource(helperFileName);
+      if (url != null && loadHelper) {
+        DebugUtils.info("loader", "found " + url);
+        return ClassLoader.getSystemResourceAsStream(helperFileName);
+      }
+
+      url = ClassLoader.getSystemResource(fileName);
+      if (url != null) {
+        DebugUtils.info("loader", "found " + url);
+        return ClassLoader.getSystemResourceAsStream(fileName);
+      }
+
+      return null;
+    }
+  }
+
+  public static InputStream getContractClassInputStream(ClassLoader loader,
+                                                        String className) {
+    return getContractClassInputStream(loader, className, false);
+  }
+
+  @Requires("className != null")
+  public static boolean resourceExists(ClassLoader loader, String className) {
+    if (loader != null) {
+      return loader.getResource(className) != null;
+    } else {
+      return ClassLoader.getSystemResource(className) != null;
+    }
+  }
+}
diff --git a/src/com/google/java/contract/core/util/LineNumberingTokenizer.java b/src/com/google/java/contract/core/util/LineNumberingTokenizer.java
new file mode 100644
index 0000000..e727c0e
--- /dev/null
+++ b/src/com/google/java/contract/core/util/LineNumberingTokenizer.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A tokenizer that keeps track of the current line number.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant("currentLineNumber >= 1")
+public class LineNumberingTokenizer extends JavaTokenizer {
+  /**
+   * The current line number, after the last processed token.
+   */
+  protected long currentLineNumber;
+
+  /**
+   * Constructs a new LineNumberingTokenizer reading characters from
+   * {@code reader}.
+   */
+  @Requires("reader != null")
+  public LineNumberingTokenizer(Reader reader) {
+    super(reader);
+    currentLineNumber = 1;
+  }
+
+  @Override
+  protected boolean lex() throws IOException {
+    if (!super.lex()) {
+      return false;
+    }
+    if (nextToken.kind == TokenKind.SPACE
+        || nextToken.kind == TokenKind.COMMENT) {
+      int lastIndex = -1;
+      for (;;) {
+        lastIndex = nextToken.text.indexOf('\n', lastIndex + 1);
+        if (lastIndex == -1) {
+          break;
+        }
+        ++currentLineNumber;
+      }
+    }
+    return true;
+  }
+
+  @Ensures("result >= 1")
+  public long getCurrentLineNumber() {
+    return currentLineNumber;
+  }
+}
diff --git a/src/com/google/java/contract/core/util/PatternMap.java b/src/com/google/java/contract/core/util/PatternMap.java
new file mode 100644
index 0000000..177f610
--- /dev/null
+++ b/src/com/google/java/contract/core/util/PatternMap.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.core.model.ClassName;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+
+import java.util.TreeMap;
+
+/**
+ * A map that stores associations between patterns and rules. Patterns
+ * can overlap: the last registered pattern overrides previous ones.
+ *
+ * <p>Patterns are semi-qualified names (nested classes have their
+ * names flattened), optionally followed by {@code .*}. A normal
+ * pattern matches itself exactly. A star pattern matches any class
+ * whose name begins with the pattern minus the terminating
+ * {@code .*}.
+ *
+ * <p>The characters {@code .} and {@code /} can be used
+ * interchangeably in patterns and names.
+ *
+ * <p><i>Implementation note:</i> This implementation uses a ternary
+ * search tree based on {@link TreeMap}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @param <R> the type of a rule
+ */
+ at AllowUnusedImport({ Iterables.class, Predicates.class })
+ at Invariant("root != null")
+public class PatternMap<R> {
+  /**
+   * A node in the internal ternary search tree.
+   */
+  @Invariant({
+    "children != null",
+    "Iterables.all(children.keySet(), ClassName.isSimpleName())",
+    "!children.values().contains(null)"
+  })
+  protected class TernaryNode {
+    protected TreeMap<String, TernaryNode> children;
+    protected R rule;
+    protected boolean exact;
+
+    protected TernaryNode(R rule, boolean exact) {
+      children = new TreeMap<String, TernaryNode>();
+      this.rule = rule;
+      this.exact = exact;
+    }
+  }
+
+  protected TernaryNode root;
+
+  public PatternMap() {
+    root = new TernaryNode(null, false);
+  }
+
+  /**
+   * Returns the rule associated with {@code pattern}.
+   */
+  @Requires("isValidPattern(pattern)")
+  public R get(String pattern) {
+    String canon = pattern.replace('/', '.');
+    boolean exact = !canon.endsWith(".*");
+    if (!exact) {
+      canon = canon.substring(0, canon.length() - 2);
+    }
+
+    String[] parts = canon.split("\\.");
+    TernaryNode current = root;
+    R best = null;
+    for (int i = 0; i < parts.length; ++i) {
+      TernaryNode next = current.children.get(parts[i]);
+      if (next == null) {
+        break;
+      }
+      if (next.rule != null) {
+        if (next.exact) {
+          if (exact && i == parts.length - 1) {
+            best = next.rule;
+          }
+        } else {
+          best = next.rule;
+        }
+      }
+      current = next;
+    }
+    return best;
+  }
+
+  /**
+   * Returns {@code true} if {@code pattern} has another pattern
+   * overriding it, that is if there exists some name that is matched
+   * by {@code pattern} and is associated with a different rule than
+   * the one associated with {@code pattern}.
+   *
+   * <p>For example, following the calls {@code put("a.*", r1)} and
+   * {@code put("a.b.*", r2)}, {@code isOverriden("a.*")} will return
+   * {@code true} if {@code !r1.equals(r2)}.
+   *
+   * <p>This method always returns {@code false} if {@code pattern} is
+   * exact.
+   */
+  @Requires("isValidPattern(pattern)")
+  public boolean isOverriden(String pattern) {
+    String canon = pattern.replace('/', '.');
+    boolean exact = !canon.endsWith(".*");
+    if (exact) {
+      return false;
+    }
+    canon = canon.substring(0, canon.length() - 2);
+
+    String[] parts = canon.split("\\.");
+    TernaryNode current = root;
+    for (int i = 0; i < parts.length; ++i) {
+      TernaryNode next = current.children.get(parts[i]);
+      if (next == null) {
+        return false;
+      }
+      current = next;
+    }
+    return !current.children.isEmpty();
+  }
+
+  /**
+   * Associates {@code rule} with {@code pattern}.
+   */
+  @Requires({
+    "isValidPattern(pattern)",
+    "rule != null"
+  })
+  @Ensures({
+    "rule.equals(get(pattern))",
+    "!isOverriden(pattern)"
+  })
+  public void put(String pattern, R rule) {
+    String canon = pattern.replace('/', '.');
+    boolean exact = !canon.endsWith(".*");
+    if (!exact) {
+      canon = canon.substring(0, canon.length() - 2);
+    }
+
+    String[] parts = canon.split("\\.");
+
+    TernaryNode current = root;
+    TernaryNode parent = root;
+    int parentIndex = -1;
+    for (int i = 0; i < parts.length; ++i) {
+      TernaryNode next = current.children.get(parts[i]);
+      if (next == null) {
+        next = new TernaryNode(null, false);
+        current.children.put(parts[i], next);
+      }
+      if (next.rule != null && !next.exact) {
+        parent = next;
+        parentIndex = i;
+      }
+      current = next;
+    }
+
+    if (!exact) {
+      /* Override patterns beginning with this one. */
+      current.children.clear();
+    }
+
+    if (!rule.equals(parent.rule)) {
+      current.rule = rule;
+      current.exact = exact;
+    } else {
+      /*
+       * The new rule we are inserting is already specified through
+       * inheritance. Remove spurious nodes. This ensures that any
+       * overriding branch is meaningful; that is, it specifies a rule
+       * value different from the inherited one.
+       */
+      current = parent;
+      for (int i = parentIndex + 1; i < parts.length; ++i) {
+        TernaryNode next = current.children.get(parts[i]);
+        if (next.rule == null) {
+          current.children.remove(parts[i]);
+          break;
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns {@code true} if {@code pattern} is a valid pattern.
+   */
+  public static boolean isValidPattern(String pattern) {
+    if (pattern == null) {
+      return false;
+    }
+    String canon = pattern.replace('/', '.');
+    return ClassName.isQualifiedName(canon)
+        || ClassName.isStarQualifiedName(canon);
+  }
+}
diff --git a/src/com/google/java/contract/core/util/PushbackTokenizer.java b/src/com/google/java/contract/core/util/PushbackTokenizer.java
new file mode 100644
index 0000000..3ae2edf
--- /dev/null
+++ b/src/com/google/java/contract/core/util/PushbackTokenizer.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+import java.io.Reader;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * A tokenizer that supports look-ahead through a push-back interface.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({
+  "queue != null",
+  "!queue.contains(null)"
+})
+public class PushbackTokenizer extends JavaTokenizer {
+  /**
+   * Pushback queue.
+   */
+  protected Deque<Token> queue;
+
+  /**
+   * Constructs a new PushbackTokenizer reading characters from
+   * {@code reader}.
+   */
+  @Requires("reader != null")
+  public PushbackTokenizer(Reader reader) {
+    super(reader);
+    queue = new ArrayDeque<Token>();
+  }
+
+  @Requires("token != null")
+  @Ensures("token == getNextToken()")
+  public void pushback(Token token) {
+    queue.push(token);
+  }
+
+  @Override
+  public Token getNextToken() {
+    Token token = queue.peek();
+    if (token != null) {
+      return token;
+    } else {
+      return super.getNextToken();
+    }
+  }
+
+  @Override
+  public int getCurrentOffset() {
+    Token token = queue.peek();
+    if (token != null) {
+      return token.offset;
+    } else {
+      return super.getCurrentOffset();
+    }
+  }
+
+  @Override
+  public boolean hasNext() {
+    if (!queue.isEmpty()) {
+      return true;
+    } else {
+      return super.hasNext();
+    }
+  }
+
+  @Override
+  public Token next() {
+    Token token = queue.poll();
+    if (token != null) {
+      return token;
+    } else {
+      return super.next();
+    }
+  }
+
+  /**
+   * Returns the next {@code lookahead}-th token, or {@code null} if
+   * there is none. Look-ahead tokens are counted from 0.
+   */
+  @Requires("lookahead >= 0")
+  public Token peek(int lookahead) {
+    ArrayDeque<Token> tmp = new ArrayDeque<Token>();
+    for (int i = 0; i <= lookahead; ++i) {
+      if (hasNext()) {
+        tmp.push(next());
+      }
+    }
+    Token token = tmp.peek();
+    while (!tmp.isEmpty()) {
+      pushback(tmp.pop());
+    }
+    return token;
+  }
+}
diff --git a/src/com/google/java/contract/core/util/SyntheticJavaFile.java b/src/com/google/java/contract/core/util/SyntheticJavaFile.java
new file mode 100644
index 0000000..08e8bd0
--- /dev/null
+++ b/src/com/google/java/contract/core/util/SyntheticJavaFile.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.core.util;
+
+import com.google.java.contract.AllowUnusedImport;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import com.google.java.contract.util.Iterables;
+import com.google.java.contract.util.Predicates;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Map;
+import javax.tools.SimpleJavaFileObject;
+
+/**
+ * An in-memory Java source file, with mapping between contract model
+ * elements and line numbers, representing a contract source.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at AllowUnusedImport({ Iterables.class, Predicates.class })
+ at Invariant({
+  "content != null",
+  "lineNumberMap == null " +
+      "|| Iterables.all(lineNumberMap.keySet(), Predicates.between(1L, null))"
+})
+public class SyntheticJavaFile extends SimpleJavaFileObject {
+  protected byte[] content;
+  protected Map<Long, ?> lineNumberMap;
+
+  /**
+   * Constructs a new SyntheticJavaFile. This constructor wraps its
+   * argument into a SyntheticJavaFile; the objects are <em>not</em>
+   * copied.
+   *
+   * @param name the class name of the file, in qualified format
+   * @param content the content of the file
+   * @param lineNumberMap the line number mapping
+   */
+  @Requires({
+    "name != null",
+    "content != null"
+  })
+  public SyntheticJavaFile(String name, byte[] content,
+                           Map<Long, ?> lineNumberMap) {
+    super(Elements.getUriForClass(name, Kind.SOURCE), Kind.SOURCE);
+    this.content = content;
+    this.lineNumberMap = lineNumberMap;
+  }
+
+  @Override
+  public InputStream openInputStream() {
+    return new ByteArrayInputStream(content);
+  }
+
+  @Override
+  public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+    return new String(content);
+  }
+
+  @Override
+  public boolean delete() {
+    content = null;
+    return true;
+  }
+
+  /**
+   * Returns the source information object associated with the
+   * specified line number.
+   */
+  public Object getSourceInfo(long lineNumber) {
+    return lineNumberMap == null ? null : lineNumberMap.get(lineNumber);
+  }
+}
diff --git a/src/com/google/java/contract/util/Iterables.java b/src/com/google/java/contract/util/Iterables.java
new file mode 100644
index 0000000..d590bb7
--- /dev/null
+++ b/src/com/google/java/contract/util/Iterables.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.util;
+
+/**
+ * Utilities for iterables.
+ *
+ * <p>These methods are intentionally name-compatible with
+ * {@link com.google.common.collect.Iterables}, so as to make it easy
+ * to switch between them.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public final class Iterables {
+  private Iterables() {
+  }
+
+  /**
+   * Applies {@code all(p)} to {@code it}.
+   *
+   * <p><b>Warning:</b> this method accepts a {@code null} iterable
+   * object and returns {@code false}. The similarly-named method in
+   * {@link com.google.common.collect.Iterables} does <em>not</em> take
+   * {@code null} as input.
+   */
+  public static <T> boolean all(Iterable<T> it, Predicate<? super T> p) {
+    if (it == null) {
+      return false;
+    }
+    for (T elem : it) {
+      if (!p.apply(elem)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Applies {@code any(p)} to {@code it}.
+   *
+   * <p><b>Warning:</b> this method accepts a {@code null} iterable
+   * object and returns {@code false}. The similarly-named method in
+   * {@link com.google.common.collect.Iterables} does <em>not</em> take
+   * {@code null} as input.
+   */
+  public static <T> boolean any(Iterable<T> it, Predicate<? super T> p) {
+    if (it == null) {
+      return false;
+    }
+    for (T elem : it) {
+      if (p.apply(elem)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/src/com/google/java/contract/util/Objects.java b/src/com/google/java/contract/util/Objects.java
new file mode 100644
index 0000000..61c61e4
--- /dev/null
+++ b/src/com/google/java/contract/util/Objects.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.util;
+
+/**
+ * Utilities for objects.
+ *
+ * <p>These methods are intentionally name-compatible with
+ * {@link com.google.common.base.Objects}, so as to make it easy
+ * to switch between them.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public final class Objects {
+  private Objects() {
+  }
+
+  /**
+   * Returns {@code true} if both its arguments are {@code null} or
+   * they compare equal.
+   */
+  public static <T> boolean equal(T a, T b) {
+    return a == null && b == null || a.equals(b);
+  }
+}
diff --git a/src/com/google/java/contract/util/Predicate.java b/src/com/google/java/contract/util/Predicate.java
new file mode 100644
index 0000000..335f564
--- /dev/null
+++ b/src/com/google/java/contract/util/Predicate.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.util;
+
+/**
+ * A function-object that returns a boolean.
+ *
+ * <p>This interface is intentionally name-compatible with
+ * {@link com.google.common.base.Predicate}, so as to make it easy to
+ * switch between them through static imports.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @param <T> the type of input to this predicate
+ */
+public interface Predicate<T> {
+  /**
+   * Applies this predicate to {@code obj}.
+   */
+  public boolean apply(T obj);
+}
diff --git a/src/com/google/java/contract/util/Predicates.java b/src/com/google/java/contract/util/Predicates.java
new file mode 100644
index 0000000..c93522b
--- /dev/null
+++ b/src/com/google/java/contract/util/Predicates.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.util;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utilities for predicates.
+ *
+ * <p>These methods are intentionally name-compatible with
+ * {@link com.google.common.base.Predicates}, so as to make it easy
+ * to switch between them.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public final class Predicates {
+  private static final Predicate<Object> TRUE = new Predicate<Object>() {
+    @Override
+    public boolean apply(Object obj) {
+      return true;
+    }
+  };
+
+  private static final Predicate<Object> FALSE = new Predicate<Object>() {
+    @Override
+    public boolean apply(Object obj) {
+      return false;
+    }
+  };
+
+  private static final Predicate<Object> IS_NULL = new Predicate<Object>() {
+    @Override
+    public boolean apply(Object obj) {
+      return obj == null;
+    }
+  };
+
+  private static final Predicate<Object> NON_NULL = new Predicate<Object>() {
+    @Override
+    public boolean apply(Object obj) {
+      return obj != null;
+    }
+  };
+
+  private Predicates() {
+  }
+
+  /**
+   * Narrows {@code p} to apply to type {@code T}.
+   */
+  @SuppressWarnings("unchecked")
+  public static <S, T extends S> Predicate<T> narrow(Predicate<S> p) {
+    return (Predicate<T>) p;
+  }
+
+  /**
+   * Returns the constant predicate that always returns {@code b}.
+   */
+  public static <T> Predicate<T> constant(final boolean b) {
+    return b
+        ? Predicates.<Object, T>narrow(TRUE)
+        : Predicates.<Object, T>narrow(FALSE);
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument is equal to {@code obj}.
+   */
+  public static <T> Predicate<T> equalTo(final T obj) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T o) {
+        return Objects.equal(o, obj);
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument is {@code null}.
+   */
+  public static <T> Predicate<T> isNull() {
+    return Predicates.<Object, T>narrow(IS_NULL);
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument is not {@code null}.
+   */
+  public static <T> Predicate<T> nonNull() {
+    return Predicates.<Object, T>narrow(NON_NULL);
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument is between {@code low} (inclusive) and {@code high}
+   * (exclusive).
+   */
+  public static <T extends Comparable<T>> Predicate<T> between(
+      final T low, final T high) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T obj) {
+        return obj != null
+            && (low == null || obj.compareTo(low) >= 0)
+            && (high == null || obj.compareTo(high) < 0);
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument is a member of {@code it}.
+   */
+  public static <T> Predicate<T> in(final Iterable<T> it) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T obj) {
+        for (T elem : it) {
+          if (Objects.equal(elem, obj)) {
+            return true;
+          }
+        }
+        return false;
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument is a member of {@code c}.
+   */
+  public static <T> Predicate<T> in(final Collection<T> c) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T obj) {
+        return c.contains(obj);
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument does not satisfy {@code p}.
+   */
+  public static <T> Predicate<T> not(final Predicate<? super T> p) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T obj) {
+        return !p.apply(obj);
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument satisfies all predicates {@code ps}.
+   */
+  public static <T> Predicate<T> and(final Predicate<? super T>... ps) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T obj) {
+        for (Predicate<? super T> p : ps) {
+          if (!p.apply(obj)) {
+            return false;
+          }
+        }
+        return true;
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if its
+   * argument satisfies any of the predicates {@code ps}.
+   */
+  public static <T> Predicate<T> or(final Predicate<? super T>... ps) {
+    return new Predicate<T>() {
+      @Override
+      public boolean apply(T obj) {
+        for (Predicate<? super T> p : ps) {
+          if (p.apply(obj)) {
+            return true;
+          }
+        }
+        return false;
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if all the
+   * elements of its argument satisfies {@code p}.
+   */
+  public static <T> Predicate<Iterable<T>> all(
+      final Predicate<? super T> p) {
+    return new Predicate<Iterable<T>>() {
+      @Override
+      public boolean apply(Iterable<T> obj) {
+        return Iterables.all(obj, p);
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if any element
+   * of its argument satisfies {@code p}.
+   */
+  public static <T> Predicate<Iterable<T>> any(
+      final Predicate<? super T> p) {
+    return new Predicate<Iterable<T>>() {
+      @Override
+      public boolean apply(Iterable<T> obj) {
+        return Iterables.any(obj, p);
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if the entry
+   * set of its argument satisfies {@code p}.
+   */
+  public static <K, V> Predicate<Map<K, V>> forEntries(
+      final Predicate<? super Set<Map.Entry<K, V>>> p) {
+    return new Predicate<Map<K, V>>() {
+      @Override
+      public boolean apply(Map<K, V> obj) {
+        return p.apply(obj.entrySet());
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if the key set
+   * of its argument satisfies {@code p}.
+   */
+  public static <K, V> Predicate<Map<K, V>> forKeys(
+      final Predicate<? super Set<K>> p) {
+    return new Predicate<Map<K, V>>() {
+      @Override
+      public boolean apply(Map<K, V> obj) {
+        return p.apply(obj.keySet());
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that evaluates to {@code true} if the value
+   * collection of its argument satisfies {@code p}.
+   */
+  public static <K, V> Predicate<Map<K, V>> forValues(
+      final Predicate<? super Collection<V>> p) {
+    return new Predicate<Map<K, V>>() {
+      @Override
+      public boolean apply(Map<K, V> obj) {
+        return p.apply(obj.values());
+      }
+    };
+  }
+
+  /**
+   * Returns a predicate that applies {@code any(p)} to the entries of
+   * its argument.
+   */
+  public static <K, V> Predicate<Map<K, V>> anyEntry(
+      Predicate<? super Map.Entry<K, V>> p) {
+    return forEntries(Predicates.<Map.Entry<K, V>>any(p));
+  }
+
+  /**
+   * Returns a predicate that applies {@code any(p)} to the keys of
+   * its argument.
+   */
+  public static <K, V> Predicate<Map<K, V>> anyKey(Predicate<? super K> p) {
+    return forKeys(Predicates.<K>any(p));
+  }
+
+  /**
+   * Returns a predicate that applies {@code any(p)} to the values of
+   * its argument.
+   */
+  public static <K, V> Predicate<Map<K, V>> anyValue(Predicate<? super V> p) {
+    return forValues(Predicates.<V>any(p));
+  }
+
+  /**
+   * Returns a predicate that applies {@code all(p)} to the entries of
+   * its argument.
+   */
+  public static <K, V> Predicate<Map<K, V>> allEntries(
+      Predicate<? super Map.Entry<K, V>> p) {
+    return forEntries(Predicates.<Map.Entry<K, V>>all(p));
+  }
+
+  /**
+   * Returns a predicate that applies {@code all(p)} to the keys of
+   * its argument.
+   */
+  public static <K, V> Predicate<Map<K, V>> allKeys(Predicate<? super K> p) {
+    return forKeys(Predicates.<K>all(p));
+  }
+
+  /**
+   * Returns a predicate that applies {@code all(p)} to the values of
+   * its argument.
+   */
+  public static <K, V> Predicate<Map<K, V>> allValues(Predicate<? super V> p) {
+    return forValues(Predicates.<V>all(p));
+  }
+}
diff --git a/test/com/google/java/contract/examples/ArrayListStack.java b/test/com/google/java/contract/examples/ArrayListStack.java
new file mode 100644
index 0000000..67af6bc
--- /dev/null
+++ b/test/com/google/java/contract/examples/ArrayListStack.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.examples;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+
+import java.util.ArrayList;
+
+/**
+ * An implementation of the {@link Stack} example interface using an
+ * {@link ArrayList}, demonstrating the use of contracts.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @param <T> the type of an element
+ */
+ at Invariant("elements != null")
+public class ArrayListStack<T> implements Stack<T> {
+  protected ArrayList<T> elements;
+
+  public ArrayListStack() {
+    elements = new ArrayList<T>();
+  }
+
+  @Override
+  public int size() {
+    return elements.size();
+  }
+
+  @Override
+  public T peek() {
+    return elements.get(elements.size() - 1);
+  }
+
+  @Override
+  public T pop() {
+    return elements.remove(elements.size() - 1);
+  }
+
+  @Override
+  @Ensures("elements.contains(old (obj))")
+  public void push(T obj) {
+    elements.add(obj);
+  }
+}
diff --git a/test/com/google/java/contract/examples/Stack.java b/test/com/google/java/contract/examples/Stack.java
new file mode 100644
index 0000000..4e2f2ce
--- /dev/null
+++ b/test/com/google/java/contract/examples/Stack.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.examples;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+/**
+ * A simple stack interface demonstrating the use of contracts. This
+ * interface does not extend java.lang.Collection as we are lazy and
+ * want a small example. Besides, Collection itself is not contracted,
+ * and some of the contracts would more logically fit there than in
+ * this interface.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ * @param <T> the type of an element
+ */
+ at Invariant("size() >= 0")
+public interface Stack<T> {
+  /**
+   * Returns the number of elements in this stack.
+   */
+  public int size();
+
+  /**
+   * Returns the topmost element of this stack without removing it.
+   */
+  @Requires("size() >= 1")
+  public T peek();
+
+  /**
+   * Pops the topmost element off this stack.
+   */
+  @Requires("size() >= 1")
+  @Ensures({
+    "size() == old (size()) - 1",
+    "result == old (peek())"
+  })
+  public T pop();
+
+  /**
+   * Pushes an element onto the stack.
+   */
+  @Ensures({
+    "size() == old (size()) + 1",
+    "peek() == old (obj)"
+  })
+  public void push(T obj);
+}
diff --git a/test/com/google/java/contract/tests/Cofoja.java b/test/com/google/java/contract/tests/Cofoja.java
new file mode 100644
index 0000000..bd0a6b7
--- /dev/null
+++ b/test/com/google/java/contract/tests/Cofoja.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.ContractEnvironment;
+import com.google.java.contract.ContractEnvironmentConfigurator;
+
+/**
+ * Contracts for Java configuration and initialization.
+ */
+public class Cofoja implements ContractEnvironmentConfigurator {
+  static ContractEnvironment contractEnv;
+
+  @Override
+  public void configure(ContractEnvironment env) {
+    contractEnv = env;
+  }
+}
diff --git a/test/com/google/java/contract/tests/ConstantContracts.java b/test/com/google/java/contract/tests/ConstantContracts.java
new file mode 100644
index 0000000..291c759
--- /dev/null
+++ b/test/com/google/java/contract/tests/ConstantContracts.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+/**
+ * This class exposes some constant contracts.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+class ConstantContracts {
+  @Requires("false || false")
+  public void preFailure() {
+  }
+
+  @Ensures("false")
+  public void postFailure() {
+  }
+
+  @Requires("true")
+  @Ensures("false")
+  public void postFailure1() {
+  }
+
+  @Requires("true")
+  @Ensures({ "false && false || false", "true", "true && false" })
+  public void postFailure2() {
+  }
+
+  @Requires("true")
+  public void preSuccess() {
+  }
+
+  @Ensures("true")
+  public void postSuccess() {
+  }
+
+  @Requires("true")
+  @Ensures("true")
+  public void postSuccess1() {
+  }
+
+  @Requires("true")
+  @Ensures("true")
+  public void postSuccess2() {
+  }
+
+  @Requires({ "true", "true" })
+  @Ensures("true")
+  public void postSuccess3() {
+  }
+}
diff --git a/test/com/google/java/contract/tests/ConstantContractsTest.java b/test/com/google/java/contract/tests/ConstantContractsTest.java
new file mode 100644
index 0000000..060afcd
--- /dev/null
+++ b/test/com/google/java/contract/tests/ConstantContractsTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts made of constant expressions.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class ConstantContractsTest extends TestCase {
+  ConstantContracts sample;
+
+  @Override
+  protected void setUp() {
+    sample = new ConstantContracts();
+  }
+
+  public void testPreFailsAndHasCorrectMessage() {
+    try {
+      sample.preFailure();
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[false || false]", expected.getMessages().toString());
+    }
+  }
+
+  public void testPostFailure() {
+    try {
+      sample.postFailure();
+      fail();
+    } catch (PostconditionError expected) {
+      /* Expected. */
+    }
+  }
+
+  public void testPostFailure1() {
+    try {
+      sample.postFailure1();
+      fail();
+    } catch (PostconditionError expected) {
+      /* Expected. */
+    }
+  }
+
+  public void testPostFailure2() {
+    try {
+      sample.postFailure2();
+      fail();
+    } catch (PostconditionError expected) {
+      /* Expected. */
+    }
+  }
+
+  public void testPreSuccess() {
+    sample.preSuccess();
+  }
+
+  public void testPostSuccess() {
+    sample.postSuccess();
+  }
+
+  public void testPostSuccess1() {
+    sample.postSuccess1();
+  }
+
+  public void testPostSuccess2() {
+    sample.postSuccess2();
+  }
+
+  public void testPostSuccess3() {
+    sample.postSuccess3();
+  }
+}
diff --git a/test/com/google/java/contract/tests/ConstructorTest.java b/test/com/google/java/contract/tests/ConstructorTest.java
new file mode 100644
index 0000000..39dd1ef
--- /dev/null
+++ b/test/com/google/java/contract/tests/ConstructorTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+import junit.framework.TestCase;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * Tests contracts that apply to constructors.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class ConstructorTest extends TestCase {
+  @Invariant("a >= 0")
+  private static class A {
+    protected int a;
+
+    public A(int x) {
+      /* Bogus for x < 0. */
+      a = x;
+    }
+  }
+
+  private static class B extends A {
+    public B(int x) {
+      /* Bogus for x < 0. */
+      super(x);
+    }
+  }
+
+  private static class C extends A {
+    @Requires("x >= 1")
+    public C(int x) {
+      super(x);
+    }
+  }
+
+  /* double super argument. */
+  private static class D {
+    @Requires("x >= 0")
+    public D(double x) {
+    }
+  }
+
+  private static class Dx extends D {
+    public Dx(double x) {
+      super(x);
+    }
+  }
+
+  /* char super argument. */
+  private static class Ch {
+    @Requires("x != '\0'")
+    public Ch(char x) {
+    }
+  }
+
+  private static class Chx extends Ch {
+    public Chx(char x) {
+      super(x);
+    }
+  }
+
+  private static class In extends FileInputStream {
+    @Requires("!name.equals(\"/dev/null\")")
+    public In(String name) throws FileNotFoundException {
+      super(name);
+    }
+  }
+
+  public void testA() {
+    A b = new A(84);
+  }
+
+  public void testABogus() {
+    try {
+      A b = new A(-64390);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testB() {
+    B b = new B(1846);
+  }
+
+  public void testBBogus() {
+    try {
+      B b = new B(-3829);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testCInvalidArgument() {
+    try {
+      C b = new C(0);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x >= 1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testDx() {
+    try {
+      Dx dx = new Dx(-3.0);
+    } catch (PreconditionError expected) {
+      assertEquals("[x >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testChx() {
+    try {
+      Chx chx = new Chx('\0');
+    } catch (PreconditionError expected) {
+      assertEquals("[x != '\0']", expected.getMessages().toString());
+    }
+  }
+
+  public void testIn() {
+    try {
+      In in = new In("XXX");
+      fail();
+    } catch (FileNotFoundException expected) {
+      /* File 'XXX' does not exist. */
+    }
+  }
+
+  public void testInInvalidArgument() throws FileNotFoundException {
+    try {
+      In in = new In("/dev/null");
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[!name.equals(\"/dev/null\")]", expected.getMessages().toString());
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/ContractedAnnotationTest.java b/test/com/google/java/contract/tests/ContractedAnnotationTest.java
new file mode 100644
index 0000000..caf631a
--- /dev/null
+++ b/test/com/google/java/contract/tests/ContractedAnnotationTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+
+/**
+ * Tests that the annotation processor handles correctly contracts applied
+ * to annotation types, ignoring them, but maintaining annotation's
+ * informations.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class ContractedAnnotationTest extends TestCase {
+  /**
+   * If this annotation verifies it's contracts, a failure should be produced.
+   */
+  @Retention(RetentionPolicy.RUNTIME)
+  @Invariant("false")
+  private static @interface MyAnnotation {
+    @Requires("false")
+    String value() default "none";
+  }
+
+  /**
+   * Tester class, uses the annotation defined above.
+   */
+  @MyAnnotation("X")
+  private static class UsesAnnotations {
+    @MyAnnotation
+    public void m1() {}
+    @MyAnnotation
+    public void m2() {}
+    @MyAnnotation
+    public void m3() {}
+    @MyAnnotation
+    public void m4() {}
+
+    @Requires("anno.value().equals(\"error\")")
+    public void trickyContract(MyAnnotation anno) {}
+
+    @Requires("anno.value().equals(\"none\")")
+    public void trickyContractDefaultValue(MyAnnotation anno) {}
+  }
+
+  UsesAnnotations uses;
+
+  public void testInnerAnnotation() {
+    uses = new UsesAnnotations();
+  }
+
+  /*
+   * Test that annotations effectively do not trigger contracts.
+   */
+  public void testEmptyAnnotationContracts() {
+    Class<UsesAnnotations> ua = UsesAnnotations.class;
+    MyAnnotation anno = ua.getAnnotation(MyAnnotation.class);
+    assertEquals("X", anno.value());
+
+    /* All methods are annotated with the default value. */
+    for (Method m : ua.getMethods()) {
+      anno = m.getAnnotation(MyAnnotation.class);
+      if (anno != null) {
+        assertEquals("none", anno.value());
+      }
+    }
+
+  }
+
+  public void testAnnotationOnContract() throws SecurityException,
+                                                NoSuchMethodException {
+    uses = new UsesAnnotations();
+    Class<UsesAnnotations> ua = UsesAnnotations.class;
+    MyAnnotation xanno = ua.getAnnotation(MyAnnotation.class);
+    try {
+      uses.trickyContract(xanno);
+      fail();
+    } catch (PreconditionError e) {
+      /* Should catch this. */
+    }
+
+    Method m1 = ua.getMethod("m1", (Class<?>[]) null);
+    MyAnnotation danno = m1.getAnnotation(MyAnnotation.class);
+    try {
+      uses.trickyContractDefaultValue(danno);
+    } catch (PreconditionError e) {
+      fail();
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/ContractedClass.java b/test/com/google/java/contract/tests/ContractedClass.java
new file mode 100644
index 0000000..9468d76
--- /dev/null
+++ b/test/com/google/java/contract/tests/ContractedClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+
+/**
+ * A dumb contracted class.
+ */
+ at Invariant("true")
+class ContractedClass {
+}
diff --git a/test/com/google/java/contract/tests/EmptyContracts.java b/test/com/google/java/contract/tests/EmptyContracts.java
new file mode 100644
index 0000000..c336aa1
--- /dev/null
+++ b/test/com/google/java/contract/tests/EmptyContracts.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+
+/**
+ * This class exposes some empty contracts that should be
+ * ignored. Note also that not specifying the value is illegal for
+ * a contract annotation, but is not enforced by OpenJDK javac when
+ * using -proc:only; hence the warnings may differ between normal
+ * compilation and contract compilation.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at Invariant({})
+class EmptyContracts {
+  @Requires({})
+  @Ensures({})
+  void emptiness() {
+  }
+}
diff --git a/test/com/google/java/contract/tests/EnclosedExtendsEnclosing.java b/test/com/google/java/contract/tests/EnclosedExtendsEnclosing.java
new file mode 100644
index 0000000..d34c4a0
--- /dev/null
+++ b/test/com/google/java/contract/tests/EnclosedExtendsEnclosing.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+
+/**
+ * A simple enclosed class that extends the enclosing one and is contracted.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class EnclosedExtendsEnclosing {
+  @Invariant("field != 0")
+  static class Enclosed extends EnclosedExtendsEnclosing {
+    private int field;
+    Enclosed(int field) {
+      this.field = field;
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/EnclosedExtendsEnclosingNoContracts.java b/test/com/google/java/contract/tests/EnclosedExtendsEnclosingNoContracts.java
new file mode 100644
index 0000000..9aa106b
--- /dev/null
+++ b/test/com/google/java/contract/tests/EnclosedExtendsEnclosingNoContracts.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package com.google.java.contract.tests;
+
+/**
+ * A simple enclosed class extending the enclosed.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class EnclosedExtendsEnclosingNoContracts {
+  static class Enclosed extends EnclosedExtendsEnclosingNoContracts {
+    private int field;
+    Enclosed(int field) {
+      this.field = field;
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/EnclosedExtendsEnclosingTest.java b/test/com/google/java/contract/tests/EnclosedExtendsEnclosingTest.java
new file mode 100644
index 0000000..3fc5f6c
--- /dev/null
+++ b/test/com/google/java/contract/tests/EnclosedExtendsEnclosingTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package com.google.java.contract.tests;
+
+import com.google.java.contract.InvariantError;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that ContractFinder finds contracts on when an enclosed class extends
+ * the enclosing one.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class EnclosedExtendsEnclosingTest extends TestCase {
+
+  public void testNoContracts() {
+    /*
+     * Simply check if the annotation processor can handle this
+     * configuration. In the past there was bug that caused infinite recursion
+     * with this.
+     */
+    EnclosedExtendsEnclosingNoContracts o =
+        new EnclosedExtendsEnclosingNoContracts.Enclosed(0);
+  }
+
+  public void testContracts() {
+    try {
+      EnclosedExtendsEnclosing o = new EnclosedExtendsEnclosing.Enclosed(0);
+    } catch (InvariantError e) {
+      /* Bogus implementation. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/EnumTest.java b/test/com/google/java/contract/tests/EnumTest.java
new file mode 100644
index 0000000..09b7086
--- /dev/null
+++ b/test/com/google/java/contract/tests/EnumTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts that apply to enum classes.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class EnumTest extends TestCase {
+  private static enum E {
+    X, Y, Z;
+
+    @Requires("this != Z")
+    public int f() {
+      return this == X ? 1 : 2;
+    }
+  }
+
+  private static enum F {
+    X(1), Y(2), Z(3);
+
+    private F(int x) {
+    }
+
+    @Requires("this != Z")
+    public int f() {
+      return this == X ? 1 : 2;
+    }
+  }
+
+  public void testX() {
+    E e = E.X;
+    e.f();
+  }
+
+  public void testZ() {
+    E e = E.Z;
+  }
+
+  public void testZIllegalState() {
+    E e = E.Z;
+    try {
+      e.f();
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[this != Z]", expected.getMessages().toString());
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/ExceptionInPredicateTest.java b/test/com/google/java/contract/tests/ExceptionInPredicateTest.java
new file mode 100644
index 0000000..96f8157
--- /dev/null
+++ b/test/com/google/java/contract/tests/ExceptionInPredicateTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests predicates with checked and unchecked exceptions.
+ *
+ * @author davidmorgan at google.com (David Morgan)
+ */
+public class ExceptionInPredicateTest extends TestCase {
+  @Requires("((Object) null).toString() == null")
+  public void predicateThrowsNullPointerException() {
+  }
+
+  @Requires("Integer.parseInt(\"z\") == 0")
+  public void predicateThrowsNumberFormatException() {
+  }
+
+  public void testRuntimeException() {
+    try {
+      predicateThrowsNullPointerException();
+      fail();
+    } catch (PreconditionError expected) {
+      assertTrue(expected.getMessage().contains("NullPointerException"));
+    }
+  }
+
+  public void testCheckedException() {
+    try {
+      predicateThrowsNumberFormatException();
+      fail();
+    } catch (PreconditionError expected) {
+      assertTrue(expected.getMessage().contains("NumberFormatException"));
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/FinalFieldsTest.java b/test/com/google/java/contract/tests/FinalFieldsTest.java
new file mode 100644
index 0000000..09e70bc
--- /dev/null
+++ b/test/com/google/java/contract/tests/FinalFieldsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that invariants are correctly applied to final fields, which can
+ * be initialized during the constructor call or before.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class FinalFieldsTest extends TestCase {
+  private static interface FinalFieldInterface {
+    public final int FIELD = 42;
+    @Requires("FIELD == 42")
+    public void success();
+    @Requires("FIELD != 42")
+    public void fail();
+  }
+
+  public void testFinalField() {
+    @Invariant("field == 1")
+    class ContractedFinalField {
+      private final int field;
+
+      public ContractedFinalField(int field) {
+        this.field = field;
+      }
+    }
+
+    ContractedFinalField cff = new ContractedFinalField(1);
+    try {
+      new ContractedFinalField(0);
+    } catch (InvariantError e) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testContractedConstant() {
+    @Invariant("FIELD == 1")
+    class ContractedConstant {
+      private static final int FIELD = 1;
+
+      @Requires("FIELD != 1")
+      public void fail() {
+        /* The contract of this method causes it to fail. */
+      }
+    }
+
+    ContractedConstant cc = new ContractedConstant();
+    try {
+      cc.fail();
+    } catch(PreconditionError e) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testContractedFinalDefaultValue() {
+    @Invariant("field == 1")
+    class ContractedFinalDefautValue {
+      private final int field = 1;
+
+      @Requires("field != 1")
+      public void fail() {
+        /* The contract of this method causes it to fail. */
+      }
+    }
+
+    ContractedFinalDefautValue cfdv = new ContractedFinalDefautValue();
+    try {
+      cfdv.fail();
+    } catch (PreconditionError e) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testFinalInterface() {
+    class Implementor implements FinalFieldInterface {
+      @Override
+      public void success() {
+        /* The contract of this method should not throw an exception. */
+      }
+      @Override
+      public void fail() {
+        /* The contract of this method causes it to fail. */
+      }
+    }
+
+    Implementor implementor = new Implementor();
+    implementor.success();
+    try {
+      implementor.fail();
+    } catch (PreconditionError e) {
+      /* Bogus implementation. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/GenericsTest.java b/test/com/google/java/contract/tests/GenericsTest.java
new file mode 100644
index 0000000..f5f576c
--- /dev/null
+++ b/test/com/google/java/contract/tests/GenericsTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts that apply to generic classes and interfaces.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class GenericsTest extends TestCase {
+  @Invariant("a.length() >= 2")
+  private static class A<T> {
+    protected String a;
+
+    public A(T x) {
+      /* Bogus for some values of x (for example, ""). */
+      a = x.toString();
+    }
+  }
+
+  private static class B extends A<Integer> {
+    /*
+     * Note: the super call is always the *first* thing to be executed
+     * in a constructor; it also means the call is made before any
+     * preconditions. In this case, the invariant of class A gets
+     * executed before the precondition of the constructor of B. This
+     * is a counter-intuitive.
+     */
+    @Requires("x >= 9")
+    public B(int x) {
+      super(x);
+    }
+  }
+
+  private static class S<T> {
+    private T x;
+
+    public S(T x) {
+      this.x = x;
+    }
+
+    @Override
+    public String toString() {
+      return x.toString();
+    }
+  }
+
+  private static class C<U extends S> extends A<U> {
+    public C(U u) {
+      super(u);
+    }
+  }
+
+  private static class D<T> {
+    private A<S<T>> a;
+
+    public D(T x) {
+      a = new C<S<T>>(new S<T>(x));
+    }
+  }
+
+  private static interface I {
+    @Requires("x.toString().length() >= 1")
+    @Ensures("result >= 1")
+    public <T> int f(T x);
+  }
+
+  private static class E implements I {
+    @Override
+    public <T> int f(T x) {
+      return x.toString().length();
+    }
+  }
+
+  private static interface J<T> {
+    @Requires("x.toString().length() >= 2")
+    @Ensures("result >= 2")
+    public int g(T x);
+  }
+
+  private static class F implements J<Integer> {
+    @Override
+    public int g(Integer x) {
+      return x.toString().length();
+    }
+  }
+
+  private static class T<X extends Throwable> {
+    /* Test ability to contract methods that throw type parameters. */
+    @Requires("true")
+    public void f(X x) throws X {
+      throw x;
+    }
+  }
+
+  private static class Npe extends T<NullPointerException> {
+    @Override
+    @Ensures("true")
+    public void f(NullPointerException x) throws NullPointerException {
+      throw x;
+    }
+  }
+
+  public void testB() {
+    B b = new B(48);
+  }
+
+  public void testBBogus() {
+    try {
+      B b = new B(9);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a.length() >= 2]", expected.getMessages().toString());
+    }
+  }
+
+  public void testC() {
+    C<S<Integer>> c = new C<S<Integer>>(new S<Integer>(283));
+  }
+
+  public void testCBogus() {
+    try {
+      C<S<Integer>> c = new C<S<Integer>>(new S<Integer>(3));
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a.length() >= 2]", expected.getMessages().toString());
+    }
+  }
+
+  public void testD() {
+    D<Integer> d = new D<Integer>(new Integer(7892));
+  }
+
+  public void testDBogus() {
+    try {
+      D<Integer> d = new D<Integer>(new Integer(4));
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a.length() >= 2]", expected.getMessages().toString());
+    }
+  }
+
+  public void testE() {
+    E e = new E();
+    e.f(23);
+  }
+
+  public void testEBogus() {
+    try {
+      E e = new E();
+      e.f("");
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x.toString().length() >= 1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testF() {
+    F f = new F();
+    f.g(79);
+  }
+
+  public void testFBogus() {
+    try {
+      F f = new F();
+      f.g(1);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x.toString().length() >= 2]", expected.getMessages().toString());
+    }
+  }
+
+  public void testT() {
+    Npe npe = new Npe();
+    try {
+      npe.f(new NullPointerException());
+      fail();
+    } catch (NullPointerException e) {
+      /* Expected exception. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/InheritanceTest.java b/test/com/google/java/contract/tests/InheritanceTest.java
new file mode 100644
index 0000000..4cf8535
--- /dev/null
+++ b/test/com/google/java/contract/tests/InheritanceTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+import junit.framework.TestCase;
+
+/**
+ * Tests contract inheritance through superclasses and interfaces.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at SuppressWarnings("unused")
+public class InheritanceTest extends TestCase {
+  @Invariant("a >= 0")
+  private abstract static class A {
+    private int p;
+    protected int a;
+
+    @Requires("x >= 0")
+    public int f(int x) {
+      a = x;
+      return x;
+    }
+
+    @Requires("x == 1")
+    @Ensures("result >= old (x)")
+    public abstract int g(int x);
+
+    @Ensures("p == old (p)")
+    public void q() {
+    }
+  }
+
+  @Invariant("b >= 0 || b == -1")
+  private static class B extends A {
+    protected int b;
+
+    @Override
+    @Requires("x == -1")
+    @Ensures("result >= old (x)")
+    public int f(int x) {
+      /* Bogus for x == -1. */
+      a = b = x;
+      return x;
+    }
+
+    @Override
+    public int g(int x) {
+      return x + 1;
+    }
+
+    /*
+     * Tests that private fields are accessible from within old-value
+     * expressions even when inherited.
+     */
+    @Override
+    public void q() {
+    }
+  }
+
+  private static class C extends B {
+    @Override
+    @Requires("x >= 1")
+    public int g(int x) {
+      /* Bogus. */
+      return x - 1;
+    }
+  }
+
+  @Invariant("k() == 1")
+  private static interface I {
+    int k();
+
+    @Requires("y > x")
+    @Ensures("result > 0")
+    int h(int x, int y);
+  }
+
+  private abstract static class J implements I {
+    @Override
+    public int k() {
+      return 1;
+    }
+
+    @Override
+    public int h(int x, int y) {
+      return y - x;
+    }
+  }
+
+  private static class D extends B implements I {
+    /* Necessary so that invariants will apply. */
+    public D() {
+    }
+
+    @Override
+    public int k() {
+      return 1;
+    }
+
+    @Override
+    public int h(int x, int y) {
+      return y - x;
+    }
+  }
+
+  private static class E extends B implements I {
+    /* Necessary so that invariants will apply. */
+    public E() {
+    }
+
+    @Override
+    public int k() {
+      /* Bogus. */
+      return 2;
+    }
+
+    @Override
+    public int h(int x, int y) {
+      return y - x;
+    }
+  }
+
+  private static class F extends B implements I {
+    /* Necessary so that invariants will apply. */
+    public F() {
+    }
+
+    @Override
+    public int k() {
+      return 1;
+    }
+
+    @Override
+    @Requires("y >= x")
+    public int h(int x, int y) {
+      /* Bogus for x == y. */
+      return y - x;
+    }
+  }
+
+  /*
+   * Complicated way to get h() through an interface call.
+   */
+  private static int getK(I obj) {
+    return obj.k();
+  }
+
+  @Invariant("getK(this) == 1")
+  private static class G extends J {
+    /* Necessary so that invariants will apply. */
+    public G() {
+    }
+  }
+
+  @Invariant("getK(this) == 2")
+  private static class H extends J {
+    /* Necessary so that invariants will apply. */
+    public H() {
+    }
+  }
+
+  B b;
+  C c;
+
+  D d;
+  F f;
+
+  @Override
+  protected void setUp() {
+
+    b = new B();
+    c = new C();
+
+    d = new D();
+    f = new F();
+  }
+
+  public void testBF() {
+    assertEquals(b.f(42), 42);
+  }
+
+  public void testBFInvalidArgument() {
+    try {
+      b.f(-36);
+      fail();
+    } catch (PreconditionError expected) {
+      /*
+       * TODO(lenh): Ordering of the messages is not predictable at
+       * the moment; the exception types should be extended with a
+       * getter to return the message array instead of just a message.
+       */
+      assertEquals("[x >= 0, x == -1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBFBogusArgument() {
+    try {
+      b.f(-1);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBG() {
+    assertEquals(b.g(1), 2);
+  }
+
+  public void testBGInvalidArgument() {
+    try {
+      b.g(3);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x == 1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBQ() {
+    b.q();
+  }
+
+  public void testCGBogus() {
+    try {
+      c.g(735);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[result >= old (x)]", expected.getMessages().toString());
+    }
+  }
+
+  public void testDFBogusArgument() {
+    try {
+      d.f(-1);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[a >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testDH() {
+    assertEquals(d.h(37, 56), 19);
+  }
+
+  public void testEBogusInvariant() {
+    try {
+      E e = new E();
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[k() == 1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testFHBogusArgument() {
+    try {
+      f.h(328, 328);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[result > 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testG() {
+    G g = new G();
+  }
+
+  public void testH() {
+    try {
+      H h = new H();
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[getK(this) == 2]", expected.getMessages().toString());
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/InnerAnnotationTest.java b/test/com/google/java/contract/tests/InnerAnnotationTest.java
new file mode 100644
index 0000000..b757ee3
--- /dev/null
+++ b/test/com/google/java/contract/tests/InnerAnnotationTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that the annotation processor handles annotations defined inside
+ * contracted classes.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class InnerAnnotationTest extends TestCase {
+  @Invariant("true")
+  private static class DefinesInnerAnnotation {
+    public static @interface MyAnnotation {
+      String value() default "none";
+    }
+    @MyAnnotation
+    public int x;
+  }
+
+  DefinesInnerAnnotation dia;
+
+  public void testInnerAnnotation() {
+    dia = new DefinesInnerAnnotation();
+  }
+}
diff --git a/test/com/google/java/contract/tests/MemberContractsTest.java b/test/com/google/java/contract/tests/MemberContractsTest.java
new file mode 100644
index 0000000..8213107
--- /dev/null
+++ b/test/com/google/java/contract/tests/MemberContractsTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests simple contracts that apply to class members. This test case
+ * does not include member contracts that depend on special features
+ * such as {@code old}, {@code result} or {@code signal}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class MemberContractsTest extends TestCase {
+  @Invariant("count >= 0")
+  static class MemberContracts {
+    private int count;
+
+    public MemberContracts() {
+      count = 0;
+    }
+
+    @Requires("n >= 0")
+    public int naturalIdentity(int n) {
+      return n;
+    }
+
+    /*
+     * Used to check the internal value, to make sure
+     * contracts do not alter normal behavior.
+     */
+    public int getCount() {
+      return count;
+    }
+
+    public void add(int n) {
+      count += n;
+    }
+
+    @Requires("n >= 1")
+    @Ensures("count >= 1")
+    public void addPositive(int n) {
+      count += n;
+    }
+
+    @Requires("n >= 1")
+    @Ensures("count >= 1")
+    public void addPositiveBogus(int n) {
+      /* Error on purpose. */
+      count += n - 1;
+    }
+
+    public static boolean allNatural(int[] array) {
+      for (int n : array) {
+        if (n < 0) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    @Requires("allNatural(array)")
+    public void addNaturals(int... array) {
+      for (int n : array) {
+        add(n);
+      }
+    }
+  }
+
+  MemberContracts sample;
+
+  @Override
+  protected void setUp() {
+    sample = new MemberContracts();
+  }
+
+  public void testIdentitySuccess() {
+    assertEquals(sample.naturalIdentity(42), 42);
+  }
+
+  public void testIdentityFailure() {
+    try {
+      sample.naturalIdentity(-36);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[n >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testInvariantSuccess() {
+    sample.add(71);
+    assertEquals(sample.getCount(), 71);
+  }
+
+  public void testInvariantFailure() {
+    try {
+      sample.add(-12);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[count >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testAddChainFailure() {
+    try {
+      sample.add(234);
+      sample.add(-123);
+      sample.add(-200);
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[count >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testAddPositive() {
+    sample.addPositive(42);
+    assertEquals(sample.getCount(), 42);
+  }
+
+  public void testAddPositiveBogusSuccess() {
+    sample.addPositiveBogus(42);
+  }
+
+  public void testAddPositiveBogusFailure() {
+    try {
+      sample.addPositiveBogus(1);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[count >= 1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testAddNaturalsSuccess() {
+    sample.addNaturals(1, 2, 3, 4);
+    assertEquals(sample.getCount(), 10);
+  }
+
+  public void testAddNaturalsFailure() {
+    try {
+      sample.addNaturals(1, 2, 3, -4, 5);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[allNatural(array)]", expected.getMessages().toString());
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/NestedClassTest.java b/test/com/google/java/contract/tests/NestedClassTest.java
new file mode 100644
index 0000000..59aedde
--- /dev/null
+++ b/test/com/google/java/contract/tests/NestedClassTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts that apply to a nested class.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class NestedClassTest extends TestCase {
+  static class NestedClass {
+    @Requires("true")
+    public void nestedSuccess() {
+    }
+
+    @Requires("false")
+    public void nestedFailure() {
+    }
+
+    @Requires({ "true", "true && true" })
+    @Ensures({ "true || true", "true" })
+    public void nestedMultiSuccess() {
+    }
+
+    /*
+     * This test checks that Contracts for Java is doing its job
+     * right when parsing the contract method names that
+     * contain '$' and identifies the correct failing
+     * predicate.
+     */
+    @Requires({ "true", "true && true" })
+    @Ensures({ "true && false", "true" })
+    public void nestedSingleFailure() {
+    }
+
+    @Requires("getTrue()")
+    public void outerAccessSuccess() {
+    }
+
+    @Requires("getFalse()")
+    public void outerAccessFailure() {
+    }
+  }
+
+  private static boolean getTrue() {
+    return true;
+  }
+
+  private static boolean getFalse() {
+    return false;
+  }
+
+  NestedClass sample;
+
+  @Override
+  protected void setUp() {
+    sample = new NestedClass();
+  }
+
+  public void testNestedSuccess() {
+    sample.nestedSuccess();
+  }
+
+  public void testNestedFailure() {
+    try {
+      sample.nestedFailure();
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[false]", expected.getMessages().toString());
+    }
+  }
+
+  public void testNestedMultiSuccess() {
+    sample.nestedMultiSuccess();
+  }
+
+  public void testNestedSingleFailure() {
+    try {
+      sample.nestedSingleFailure();
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[true && false]", expected.getMessages().toString());
+    }
+  }
+
+  public void testOuterAccessSuccess() {
+    sample.outerAccessSuccess();
+  }
+
+  public void testOuterAccessFailure() {
+    try {
+      sample.outerAccessFailure();
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[getFalse()]", expected.getMessages().toString());
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/PatternMapTest.java b/test/com/google/java/contract/tests/PatternMapTest.java
new file mode 100644
index 0000000..01662df
--- /dev/null
+++ b/test/com/google/java/contract/tests/PatternMapTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.core.util.PatternMap;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link PatternMap}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class PatternMapTest extends TestCase {
+  private PatternMap<Integer> map;
+
+  @Override
+  protected void setUp() {
+    map = new PatternMap<Integer>();
+  }
+
+  public void testExactMatch() {
+    map.put("a.b.c.X", 0);
+    map.put("a.b.Y", 1);
+    map.put("a.b.c.d.Z", 2);
+    map.put("a.b.Y1", 3);
+    assertEquals(2, (int) map.get("a.b.c.d.Z"));
+    map.put("a.b.Y2", 4);
+    map.put("a.b.c.d.Z1", 5);
+    assertEquals(1, (int) map.get("a.b.Y"));
+    assertEquals(4, (int) map.get("a.b.Y2"));
+  }
+
+  public void testStarMatch() {
+    map.put("a.b.c.*", 0);
+    map.put("a.b.Y", 1);
+    map.put("a.b.c.d.Z", 2);
+    map.put("a.b.Y1", 3);
+    assertEquals(0, (int) map.get("a.b.c.X"));
+    assertEquals(2, (int) map.get("a.b.c.d.Z"));
+    map.put("a.b.Y2", 4);
+    map.put("a.b.c.d.Z1", 5);
+    assertEquals(0, (int) map.get("a.b.c.U"));
+    assertEquals(4, (int) map.get("a.b.Y2"));
+  }
+
+  public void testStarOverride() {
+    map.put("a.b.Y", 1);
+    map.put("a.b.c.d.Z", 2);
+    map.put("a.b.c.*", 0);
+    map.put("a.b.Y1", 3);
+    assertEquals(0, (int) map.get("a.b.c.X"));
+    assertEquals(0, (int) map.get("a.b.c.d.Z"));
+    map.put("a.b.Y2", 4);
+    map.put("a.b.c.d.Z1", 5);
+    assertEquals(0, (int) map.get("a.b.c.U"));
+    assertEquals(4, (int) map.get("a.b.Y2"));
+  }
+
+  public void testRedundantOverride() {
+    map.put("a.*", 0);
+    map.put("a.x.*", 1);
+    map.put("a.x.u.*", 2);
+    map.put("a.y.*", 0);
+    map.put("a.y.u.*", 0);
+    assertEquals(1, (int) map.get("a.x.X"));
+    assertEquals(0, (int) map.get("a.y.X"));
+    assertEquals(0, (int) map.get("a.a.X"));
+    assertEquals(false, map.isOverriden("a.x.u.X"));
+    assertEquals(false, map.isOverriden("a.x.u.*"));
+    assertEquals(true, map.isOverriden("a.*"));
+    assertEquals(true, map.isOverriden("a.x.*"));
+    assertEquals(false, map.isOverriden("a.y.*"));
+  }
+}
diff --git a/test/com/google/java/contract/tests/PublicCallTest.java b/test/com/google/java/contract/tests/PublicCallTest.java
new file mode 100644
index 0000000..c0e9f01
--- /dev/null
+++ b/test/com/google/java/contract/tests/PublicCallTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts on public methods for reentry.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class PublicCallTest extends TestCase {
+  @Invariant("x != 0")
+  private static class SimpleObject {
+    public int x;
+
+    public SimpleObject() {
+      x = 1;
+    }
+
+    public void f() {
+    }
+
+    public void g() {
+      x = 0;
+      f();
+      x = 1;
+    }
+
+    public void f1() {
+      x = 0;
+    }
+
+    public void g1() {
+      f1();
+      x = 1;
+    }
+  }
+
+  @Invariant("x != 0")
+  private static class A {
+    public int x;
+  }
+
+  private static class B extends A {
+    public B() {
+      x = 1;
+    }
+  }
+
+  protected SimpleObject sample;
+
+  @Override
+  protected void setUp() {
+    sample = new SimpleObject();
+  }
+
+  public void testF() {
+    sample.x = 1;
+    sample.f();
+  }
+
+  public void testG() {
+    sample.x = 1;
+    sample.g();
+  }
+
+  public void testF1() {
+    try {
+      sample.x = 1;
+      sample.f1();
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[x != 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testG1() {
+    sample.x = 1;
+    sample.g1();
+  }
+
+  public void testA() {
+    try {
+      A a = new A();
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[x != 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testB() {
+    B b = new B();
+  }
+}
diff --git a/test/com/google/java/contract/tests/ReturnTypeTest.java b/test/com/google/java/contract/tests/ReturnTypeTest.java
new file mode 100644
index 0000000..cfcd980
--- /dev/null
+++ b/test/com/google/java/contract/tests/ReturnTypeTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.PostconditionError;
+
+import junit.framework.TestCase;
+
+import java.io.Serializable;
+
+/**
+ * Tests the correct typing of result variables through contract
+ * inheritance.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+ at SuppressWarnings("unused")
+public class ReturnTypeTest extends TestCase {
+  private static class A {
+    @Ensures({
+      "result != null",
+      "result.equals(x)"
+    })
+    public Number f(int x) {
+      return x;
+    }
+  }
+
+  private static class B extends A {
+    /* Covariant return type. */
+    @Override
+    public Integer f(int x) {
+      /* Bogus. */
+      return x + 1;
+    }
+  }
+
+  private static interface I<T> {
+    @Ensures({
+      "result != null",
+      "result.equals(x)"
+    })
+    public T f(int x);
+  }
+
+  private static class C implements I<Integer> {
+    /* Specialized return type. */
+    @Override
+    public Integer f(int x) {
+      /* Bogus. */
+      return x - 1;
+    }
+  }
+
+  private static class C1 implements I<Number> {
+    /* Specialized and covariant return type. */
+    @Override
+    public Integer f(int x) {
+      /* Bogus. */
+      return x - 1;
+    }
+  }
+
+  private static class C2 extends A implements I<Comparable> {
+    /* Specialized and doubly covariant return type. */
+    @Override
+    public Integer f(int x) {
+      /* Bogus. */
+      return x - 1;
+    }
+  }
+
+  /* Complex erasure from a superclass. */
+  private abstract static class J<T extends Serializable & Comparable> {
+    @Ensures({
+      "result != null",
+      "result.compareTo(x) == 0"
+    })
+    public abstract T f(int x);
+  }
+
+  private static class D extends J<Integer> {
+    /* Specialized return type. */
+    @Override
+    public Integer f(int x) {
+      /* Bogus. */
+      return x - 1;
+    }
+  }
+
+  public void testB() {
+    try {
+      new B().f(8326);
+      fail();
+    } catch (PostconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testC() {
+    try {
+      new C().f(584);
+      fail();
+    } catch (PostconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testC1() {
+    try {
+      new C1().f(206);
+      fail();
+    } catch (PostconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testC2() {
+    try {
+      new C2().f(4896);
+      fail();
+    } catch (PostconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+
+  public void testD() {
+    try {
+      new D().f(9075);
+      fail();
+    } catch (PostconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/SelectiveContractsTest.java b/test/com/google/java/contract/tests/SelectiveContractsTest.java
new file mode 100644
index 0000000..36c5461
--- /dev/null
+++ b/test/com/google/java/contract/tests/SelectiveContractsTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.ContractEnvironment;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests selective contract activation.
+ *
+ * @see Cofoja
+ */
+public class SelectiveContractsTest extends TestCase {
+  private static class A {
+    @Requires("false")
+    public static void f() {
+    }
+  }
+
+  private static class B {
+    @Ensures("false")
+    public static void f() {
+    }
+  }
+
+  @Invariant("false")
+  private static class C {
+  }
+
+  private static class D {
+    @Requires("false")
+    @Ensures("false")
+    public static void f() {
+    }
+  }
+
+  @Invariant("false")
+  private static class E {
+    @Requires("false")
+    @Ensures("false")
+    public void f() {
+    }
+  }
+
+  @Invariant("false")
+  private static class F {
+    @Requires("false")
+    public void f() {
+    }
+  }
+
+  @Invariant("false")
+  private static interface I {
+  }
+
+  /* Missing @Contracted. */
+  private static class G implements I {
+  }
+
+  @Override
+  protected void setUp() {
+    ContractEnvironment env = Cofoja.contractEnv;
+
+    env.disablePreconditions("com.google.java.contract.tests.SelectiveContractsTest$A");
+    env.disablePostconditions("com.google.java.contract.tests.SelectiveContractsTest$B");
+    env.disableInvariants("com.google.java.contract.tests.SelectiveContractsTest$C");
+    env.disablePreconditions("com.google.java.contract.tests.SelectiveContractsTest$D");
+    env.disableInvariants("com.google.java.contract.tests.SelectiveContractsTest$E");
+
+    env.ignore("com.google.java.contract.tests.SelectiveContractsTest$F");
+    env.ignore("com.google.java.contract.tests.SelectiveContractsTest$G");
+
+    env.disableInvariants("com.google.java.contract.tests.selective.a.*");
+    env.disableInvariants("com.google.java.contract.tests.selective.b.*");
+    env.enableInvariants("com.google.java.contract.tests.selective.b.y.*");
+    env.enableInvariants("com.google.java.contract.tests.selective.a.x.X1");
+  }
+
+  public void testA() {
+    A.f();
+  }
+
+  public void testB() {
+    B.f();
+  }
+
+  public void testC() {
+    new C();
+  }
+
+  public void testD() {
+    try {
+      D.f();
+      fail();
+    } catch (PostconditionError expected) {
+      /* Expected since the precondition should be disabled. */
+    }
+  }
+
+  public void testE() {
+    try {
+      new E().f();
+      fail();
+    } catch (PreconditionError expected) {
+      /* Expected since the invariant should be disabled. */
+    }
+  }
+
+  public void testF() {
+    new F().f();
+  }
+
+  public void testG() {
+    new G();
+  }
+
+  public void testStarPattern() {
+    new com.google.java.contract.tests.selective.a.A();
+    new com.google.java.contract.tests.selective.a.x.X();
+  }
+
+  public void testOverridePattern() {
+    try {
+      new com.google.java.contract.tests.selective.a.x.X1();
+    } catch (InvariantError expected) {
+      /* Expected since the star pattern should be overriden. */
+    }
+  }
+
+  public void testOverrideStarPattern() {
+    new com.google.java.contract.tests.selective.b.B();
+    try {
+      new com.google.java.contract.tests.selective.b.y.Y();
+    } catch (InvariantError expected) {
+      /* Expected since the first star pattern should be overriden. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/SeparateGenericSuperclass.java b/test/com/google/java/contract/tests/SeparateGenericSuperclass.java
new file mode 100644
index 0000000..d0d23fe
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateGenericSuperclass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+
+/**
+ * A dummy class overriden in {@link SeparateGenericSuperclassTest}.
+ * It has some type parameter with a complex erasure.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+abstract class SeparateGenericSuperclass<T extends Number & Comparable> {
+  @Ensures({
+    "result != null",
+    "result.equals(x)"
+  })
+  public abstract T f(int x);
+}
diff --git a/test/com/google/java/contract/tests/SeparateGenericSuperclassTest.java b/test/com/google/java/contract/tests/SeparateGenericSuperclassTest.java
new file mode 100644
index 0000000..a51b899
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateGenericSuperclassTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.PostconditionError;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests inheritance of postconditions of methods returning a generic
+ * type parameter with complex erasure in a superclass compiled
+ * separately.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class SeparateGenericSuperclassTest extends TestCase {
+  private static class SeparateChild
+      extends SeparateGenericSuperclass<Integer> {
+    @Override
+    public Integer f(int x) {
+      return x + 1;
+    }
+  }
+
+  public void testF() {
+    try {
+      new SeparateChild().f(6379);
+      fail();
+    } catch (PostconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/SeparateInterface.java b/test/com/google/java/contract/tests/SeparateInterface.java
new file mode 100644
index 0000000..34c5744
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateInterface.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Johannes Rieken
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Requires;
+
+/**
+ * A dummy interface overriden in {@link SeparateInterfaceTest}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+interface SeparateInterface {
+  @Requires("x >= 0")
+  public void f(int x);
+
+  @Requires("x < y")
+  public void g(int x, int y);
+
+  @Requires("x < y + z")
+  public void h(int x, int y, int z);
+
+  @Requires("x > y")
+  public void k(int x, int y);
+}
diff --git a/test/com/google/java/contract/tests/SeparateInterfaceTest.java b/test/com/google/java/contract/tests/SeparateInterfaceTest.java
new file mode 100644
index 0000000..b5a78e4
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateInterfaceTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.PreconditionError;
+import junit.framework.TestCase;
+
+/**
+ * Tests renaming of interface method parameters.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class SeparateInterfaceTest extends TestCase {
+  private static class SeparateImplementation implements SeparateInterface {
+    @Override
+    public void f(int y) {
+    }
+
+    @Override
+    public void g(int y, int x) {
+    }
+
+    @Override
+    public void h(int y, int z, int x) {
+    }
+
+    @Override
+    public void k(int x, int y) {
+    }
+  }
+
+  private SeparateImplementation sample;
+
+  @Override
+  protected void setUp() {
+    sample = new SeparateImplementation();
+  }
+
+  public void testF() {
+    sample.f(846);
+  }
+
+  public void testFIllegalArgument() {
+    try {
+      sample.f(-67);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testG() {
+    sample.g(28, 371);
+  }
+
+  public void testGIllegalArgument() {
+    try {
+      sample.g(2485, 846);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x < y]", expected.getMessages().toString());
+    }
+  }
+
+  public void testH() {
+    sample.h(2, 1, 3);
+  }
+
+  public void testHIllegalArgument() {
+    try {
+      sample.h(3, 1, 2);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x < y + z]", expected.getMessages().toString());
+    }
+  }
+
+  public void testK() {
+    sample.k(81, 67);
+  }
+
+  public void testKIllegalArgument() {
+    try {
+      sample.k(67, 81);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x > y]", expected.getMessages().toString());
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/SeparateInvariantSuperclass.java b/test/com/google/java/contract/tests/SeparateInvariantSuperclass.java
new file mode 100644
index 0000000..9ac58bb
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateInvariantSuperclass.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Invariant;
+
+/**
+ * Separate dummy class to test contract checking through inheritance.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+ at Invariant("x != 0")
+public class SeparateInvariantSuperclass {
+  @SuppressWarnings("unused")
+  protected int x = 0;
+
+  public SeparateInvariantSuperclass() {
+    x = 1;
+  }
+
+  public void violate() {
+  }
+}
diff --git a/test/com/google/java/contract/tests/SeparateInvariantSuperclassTest.java b/test/com/google/java/contract/tests/SeparateInvariantSuperclassTest.java
new file mode 100644
index 0000000..6d9742f
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateInvariantSuperclassTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.InvariantError;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Tests that contracts are found through inheritance when declared as
+ * invariants on the superclass.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class SeparateInvariantSuperclassTest extends TestCase{
+  private static class SeparateChild extends SeparateInvariantSuperclass {
+    @Override
+    public void violate() {
+      x = 0;
+    }
+  }
+
+  private SeparateChild child;
+
+  @Override
+  protected void setUp() {
+    child = new SeparateChild();
+  }
+
+  public void testViolate() {
+    try {
+      child.violate();
+      fail();
+    } catch (InvariantError expected) {
+      /* Bogus implementation. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/SeparateMethodContractSuperclass.java b/test/com/google/java/contract/tests/SeparateMethodContractSuperclass.java
new file mode 100644
index 0000000..26cea51
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateMethodContractSuperclass.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Requires;
+
+/**
+ * Separate dummy class to test contract checking through inheritance.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class SeparateMethodContractSuperclass {
+  @Requires("false")
+  public void violate() {
+  }
+}
diff --git a/test/com/google/java/contract/tests/SeparateMethodContractSuperclassTest.java b/test/com/google/java/contract/tests/SeparateMethodContractSuperclassTest.java
new file mode 100644
index 0000000..bab6814
--- /dev/null
+++ b/test/com/google/java/contract/tests/SeparateMethodContractSuperclassTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package com.google.java.contract.tests;
+
+import com.google.java.contract.PreconditionError;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that contracts are found through inheritance when declared as
+ * method contracts on the superclass.
+ *
+ * @author chatain at google.com (Leonardo Chatain)
+ */
+public class SeparateMethodContractSuperclassTest extends TestCase {
+  private static class SeparateChild extends SeparateMethodContractSuperclass{
+    @Override
+    public void violate() {
+
+    }
+  }
+
+  private SeparateChild child;
+
+  @Override
+  protected void setUp() {
+    child = new SeparateChild();
+  }
+
+  public void testViolate() {
+    try {
+      child.violate();
+      fail();
+    } catch (PreconditionError expected) {
+      /* Bogus implementation. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/SimpleMathTest.java b/test/com/google/java/contract/tests/SimpleMathTest.java
new file mode 100644
index 0000000..7868f3b
--- /dev/null
+++ b/test/com/google/java/contract/tests/SimpleMathTest.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+import com.google.java.contract.ThrowEnsures;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts on some simple mathematical functions. Among other
+ * things, these contracts make use of {@code result} and {@code old}.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class SimpleMathTest extends TestCase {
+  private static class SimpleMath {
+    /*
+     * This is just for the test; usually, you should not reference
+     * the parameters directly, and use old() instead.
+     * TODO(lenh): Should we be able to do that at all?
+     */
+    @Ensures("result == x + y")
+    public static int add(int x, int y) {
+      return x + y;
+    }
+
+    @Ensures("result == x + y")
+    public static int bogusAdd(int x, int y) {
+      return x + y + 1;
+    }
+
+    @Requires({ "x > 0", "y > 0" })
+    @Ensures({
+      "result != 0",
+      "old (x) % result == 0",
+      "old (y) % result == 0"
+    })
+    public static int gcd(int x, int y) {
+      while (x != 0 && y != 0) {
+        if (x > y) {
+            x -= y;
+        } else {
+            y -= x;
+        }
+      }
+
+      return (x != 0) ? x : y;
+    }
+
+    @Requires({ "x > 0", "y > 0" })
+    @Ensures({
+      "result != 0",
+      "old (x) % result == 0",
+      "old (y) % result == 0"
+    })
+    public static int bogusGcd(int x, int y) {
+      while (x != 0 && y != 0) {
+        if (x > y) {
+            x -= y;
+        } else {
+            y -= x;
+        }
+      }
+
+      return (x != 0) ? y : x;
+    }
+
+    @Requires({ "x > 0", "y > 0" })
+    @Ensures({
+      "result != 0",
+      "old (x) % result == 0",
+      "old (y) % result == 0"
+    })
+    public static int bogusGcd1(int x, int y) {
+      return x;
+    }
+
+    @Requires("n >= 0")
+    @Ensures("!result || old (n) % 2 == 0")
+    public static boolean even(int n) {
+      if (n == 0) {
+        return true;
+      } else {
+        return odd(n - 1);
+      }
+    }
+
+    @Requires("n >= 0")
+    @Ensures({
+      "!result || old (n) % 2 == 1",
+      /* For testing purposes: check that old () has the right value. */
+      "old (n) == n"
+    })
+    public static boolean odd(int n) {
+      if (n == 0) {
+        return false;
+      } else {
+        return even(n - 1);
+      }
+    }
+
+    @ThrowEnsures({ "IllegalArgumentException", "old (x) < 0" })
+    public static double sqrt(double x) {
+      if (x < 0) {
+        throw new IllegalArgumentException();
+      }
+      return Math.sqrt(x);
+    }
+
+    @ThrowEnsures({ "IllegalArgumentException", "old (x) < -1" })
+    public static double bogusSqrt(double x) {
+      if (x < 0) {
+        throw new IllegalArgumentException();
+      }
+      return Math.sqrt(x);
+    }
+  }
+
+  public void testAdd() {
+    assertEquals(SimpleMath.add(1, 2), 3);
+  }
+
+  public void testBogusAdd() {
+    try {
+      SimpleMath.bogusAdd(1, 2);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[result == x + y]", expected.getMessages().toString());
+    }
+  }
+
+  public void testGcd() {
+    assertEquals(SimpleMath.gcd(83295, 37285), 5);
+  }
+
+  public void testGcdInvalidArguments() {
+    try {
+      SimpleMath.gcd(-1382, -3287);
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[x > 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBogusGcd() {
+    try {
+      SimpleMath.bogusGcd(83295, 37285);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[result != 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBogusGcd1() {
+    try {
+      SimpleMath.bogusGcd1(83295, 37285);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[old (y) % result == 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testEven() {
+    assertEquals(SimpleMath.even(392), true);
+  }
+
+  public void testSqrt() {
+    SimpleMath.sqrt(4);
+  }
+
+  public void testSqrtInvalidArgument() {
+    try {
+      SimpleMath.sqrt(-3);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      /* Expected to pass through the contract. */
+    }
+  }
+
+  public void testBogusSqrt() {
+    try {
+      SimpleMath.bogusSqrt(-0.5);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals(expected.getMessages().toString(),
+                   "[IllegalArgumentException => old (x) < -1]");
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/StackTest.java b/test/com/google/java/contract/tests/StackTest.java
new file mode 100644
index 0000000..c6e64cc
--- /dev/null
+++ b/test/com/google/java/contract/tests/StackTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.InvariantError;
+import com.google.java.contract.PostconditionError;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.examples.ArrayListStack;
+import com.google.java.contract.examples.Stack;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests implementations of {@link Stack} against the contracts
+ * specified in the interface.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class StackTest extends TestCase {
+  /**
+   * A stack implementation that does not preserve its invariant.
+   */
+  public static class BogusInvariantStack<T> implements Stack<T> {
+    @Override
+    public int size() {
+      return -1;
+    }
+
+    @Override
+    public T peek() {
+      return null;
+    }
+
+    @Override
+    public T pop() {
+      return null;
+    }
+
+    @Override
+    public void push(T obj) {
+    }
+  }
+
+  /**
+   * A stack implementation that does not preserve its postconditions.
+   */
+  public static class BogusPostconditionsStack<T>
+      extends BogusInvariantStack<T> {
+    @Override
+    public int size() {
+      return 0;
+    }
+  }
+
+  /**
+   * A stack implementation that simply counts its elements instead of
+   * storing them.
+   */
+  public static class BogusCountingStack<T>
+      extends BogusPostconditionsStack<T> {
+    protected int count;
+
+    public BogusCountingStack() {
+      count = 0;
+    }
+
+    @Override
+    public int size() {
+      return count;
+    }
+
+    @Override
+    public T pop() {
+      --count;
+      return null;
+    }
+
+    @Override
+    public void push(T obj) {
+      ++count;
+    }
+  }
+
+  /**
+   * A stack implementation that simply stores the last element. This
+   * implementation suffices to fool our contracts.
+   */
+  public static class BogusLastElementStack<T>
+      extends BogusCountingStack<T> {
+    protected T lastElement;
+
+    @Override
+    public T peek() {
+      return lastElement;
+    }
+
+    @Override
+    public T pop() {
+      --count;
+      return lastElement;
+    }
+
+    @Override
+    public void push(T obj) {
+      ++count;
+      lastElement = obj;
+    }
+  }
+
+  private Stack<Integer> stack;
+
+  @Override
+  public void setUp() {
+    stack = new ArrayListStack<Integer>();
+  }
+
+  public void testNormal() {
+    stack.push(1);
+    stack.push(2);
+    assertEquals(2, stack.size());
+    stack.pop();
+    stack.push(3);
+    stack.pop();
+    stack.pop();
+    stack.push(4);
+    assertEquals(1, stack.size());
+  }
+
+  public void testEmptyPop() {
+    try {
+      stack.pop();
+      fail();
+    } catch (PreconditionError expected) {
+      assertEquals("[size() >= 1]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBogusInvariant() {
+    try {
+      Stack<Integer> bogusInvariantStack = new BogusInvariantStack<Integer>();
+      fail();
+    } catch (InvariantError expected) {
+      assertEquals("[size() >= 0]", expected.getMessages().toString());
+    }
+  }
+
+  public void testBogusPostPush() {
+    Stack<Integer> bogusPostconditionsStack =
+        new BogusPostconditionsStack<Integer>();
+    try {
+      bogusPostconditionsStack.push(1);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[size() == old (size()) + 1]",
+                   expected.getMessages().toString());
+    }
+  }
+
+  public void testBogusPostPush1() {
+    Stack<Integer> countingStack = new BogusCountingStack<Integer>();
+    try {
+      countingStack.push(1);
+      fail();
+    } catch (PostconditionError expected) {
+      assertEquals("[peek() == old (obj)]", expected.getMessages().toString());
+    }
+  }
+
+  public void testIneffectiveBogusPostPush() {
+    Stack<Integer> lastElementStack = new BogusLastElementStack<Integer>();
+    lastElementStack.push(1);
+    lastElementStack.push(2);
+    lastElementStack.pop();
+  }
+}
diff --git a/test/com/google/java/contract/tests/VariadicTest.java b/test/com/google/java/contract/tests/VariadicTest.java
new file mode 100644
index 0000000..4ea1855
--- /dev/null
+++ b/test/com/google/java/contract/tests/VariadicTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 Nhat Minh Lê
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.PreconditionError;
+import com.google.java.contract.Requires;
+import junit.framework.TestCase;
+
+/**
+ * Tests contracts with classes that use variadic methods.
+ *
+ * @author nhat.minh.le at huoc.org (Nhat Minh Lê)
+ */
+public class VariadicTest extends TestCase {
+  private static class V {
+    @Requires("xs.length >= 2")
+    public int sub(int... xs) {
+      int acc = xs[0];
+      for (int i = 1; i < xs.length; ++i) {
+        acc -= xs[i];
+      }
+      return acc;
+    }
+
+    @Ensures("xs.length < 2 || result == sub(xs)")
+    public int subOrNeg(int... xs) {
+      switch (xs.length) {
+        case 0:
+          return 0;
+        case 1:
+          return -xs[0];
+        default:
+          int acc = xs[0];
+          for (int i = 1; i < xs.length; ++i) {
+            acc -= xs[i];
+          }
+          return acc;
+      }
+    }
+
+    public int addMultiSub(int[]... xss) {
+      int acc = 0;
+      for (int i = 0; i < xss.length; ++i) {
+        acc += sub(xss[i]);
+      }
+      return acc;
+    }
+
+    public boolean testSubs(int... xs) {
+      return xs.length < 2 ? true : sub(xs) == subOrNeg(xs);
+    }
+
+    @Requires("testSubs(1, 2, 3, 4, 5, 6)")
+    public void variadicInContract() {
+    }
+
+    @Requires("addMultiSub(new int[] { 3, 2, 1 }, new int[] { 1, 2, 3 }) == -4")
+    public void multiSubVariadicInContract() {
+    }
+
+    @Requires("false")
+    public void buggyVariadic(int... xs) {
+    }
+  }
+
+  private V v;
+
+  @Override
+  public void setUp() {
+    v = new V();
+  }
+
+  public void testSub() {
+    assertEquals(v.sub(3, 2, 1), 0);
+  }
+
+  public void testSubOrNeg() {
+    assertEquals(v.subOrNeg(3, 2, 1), 0);
+    assertEquals(v.subOrNeg(4), -4);
+  }
+
+  public void testTestSubs() {
+    assertTrue(v.testSubs(8932, 678, 20122));
+  }
+
+  public void testVariadicInContract() {
+    v.variadicInContract();
+  }
+
+  public void testMultiSubVariadicInContract() {
+    v.multiSubVariadicInContract();
+  }
+
+  public void testBuggyVariadic() {
+    try {
+      v.buggyVariadic(8932, 678, 20122);
+      fail();
+    } catch (PreconditionError e) {
+      /* Expected. */
+    }
+  }
+}
diff --git a/test/com/google/java/contract/tests/selective/a/A.java b/test/com/google/java/contract/tests/selective/a/A.java
new file mode 100644
index 0000000..be6fe87
--- /dev/null
+++ b/test/com/google/java/contract/tests/selective/a/A.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests.selective.a;
+
+import com.google.java.contract.Invariant;
+
+ at Invariant("false")
+public class A {
+}
diff --git a/test/com/google/java/contract/tests/selective/a/x/X.java b/test/com/google/java/contract/tests/selective/a/x/X.java
new file mode 100644
index 0000000..c166bbb
--- /dev/null
+++ b/test/com/google/java/contract/tests/selective/a/x/X.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests.selective.a.x;
+
+import com.google.java.contract.Invariant;
+
+ at Invariant("false")
+public class X {
+}
diff --git a/test/com/google/java/contract/tests/selective/a/x/X1.java b/test/com/google/java/contract/tests/selective/a/x/X1.java
new file mode 100644
index 0000000..27a7c41
--- /dev/null
+++ b/test/com/google/java/contract/tests/selective/a/x/X1.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests.selective.a.x;
+
+import com.google.java.contract.Invariant;
+
+ at Invariant("false")
+public class X1 {
+}
diff --git a/test/com/google/java/contract/tests/selective/b/B.java b/test/com/google/java/contract/tests/selective/b/B.java
new file mode 100644
index 0000000..d45a573
--- /dev/null
+++ b/test/com/google/java/contract/tests/selective/b/B.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests.selective.b;
+
+import com.google.java.contract.Invariant;
+
+ at Invariant("false")
+public class B {
+}
diff --git a/test/com/google/java/contract/tests/selective/b/y/Y.java b/test/com/google/java/contract/tests/selective/b/y/Y.java
new file mode 100644
index 0000000..469a52a
--- /dev/null
+++ b/test/com/google/java/contract/tests/selective/b/y/Y.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package com.google.java.contract.tests.selective.b.y;
+
+import com.google.java.contract.Invariant;
+
+ at Invariant("false")
+public class Y {
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/libcofoja-java.git



More information about the debian-med-commit mailing list